package shreder import ( "encoding/binary" "fmt" "github.com/gagliardetto/solana-go" ) var raydiumLaunchLabProgramID = solana.MustPublicKeyFromBase58("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj") var ( raydiumLaunchLabSellExactInDiscriminator = []byte{0x95, 0x27, 0xde, 0x9b, 0xd3, 0x7c, 0x98, 0x1a} raydiumLaunchLabSellExactOutDiscriminator = []byte{0x5f, 0xc8, 0x47, 0x22, 0x08, 0x09, 0x0b, 0xa6} raydiumLaunchLabBuyExactInDiscriminator = []byte{0xfa, 0xea, 0x0d, 0x7b, 0xd5, 0x9c, 0x13, 0xec} raydiumLaunchLabBuyExactOutDiscriminator = []byte{0x18, 0xd3, 0x74, 0x28, 0x69, 0x03, 0x99, 0x38} ) func parseRaydiumLaunchLabInstruction(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, raydiumLaunchLabBuyExactInDiscriminator) { txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, true, true) } else if matchMethod(instruction.Data, raydiumLaunchLabBuyExactOutDiscriminator) { txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, true, false) } else if matchMethod(instruction.Data, raydiumLaunchLabSellExactInDiscriminator) { txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, false, true) } else if matchMethod(instruction.Data, raydiumLaunchLabSellExactOutDiscriminator) { txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, false, false) } if txSignal != nil { return TxSignalBatch{txSignal}, err } return nil, err } func parseRaydiumLaunchLabSwap(tx VersionedTransaction, instruction Instructions, isBuy bool, exactIn bool) (*TxSignal, error) { if len(instruction.Accounts) < 10 { return nil, fmt.Errorf("accounts too short") } if len(instruction.Data) < 24 { return nil, fmt.Errorf("data too short for raydium launch lab swap args, len=%d", len(instruction.Data)) } mint, err := tx.GetAccount(int(instruction.Accounts[9])) if err != nil { return nil, err } user, err := tx.GetAccount(int(instruction.Accounts[0])) if err != nil { return nil, err } amountA := binary.LittleEndian.Uint64(instruction.Data[8:16]) amountB := binary.LittleEndian.Uint64(instruction.Data[16:24]) if isBuy { if exactIn { return &TxSignal{ TxHash: tx.Signatures[0].String(), Label: "raydiumlaunchlab", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(amountB), Token1Amount: formatSolAmount(amountA), Program: "RaydiumLaunchLab", Event: "buy", IsToken2022: false, IsMayhemMode: false, ExactSOL: true, Block: tx.Block, Token0AmountUint64: amountB, Token1AmountUint64: amountA, }, nil } else { return &TxSignal{ TxHash: tx.Signatures[0].String(), Label: "raydiumlaunchlab", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(amountA), Token1Amount: formatSolAmount(amountB), Program: "RaydiumLaunchLab", Event: "buy", IsToken2022: false, IsMayhemMode: false, ExactSOL: false, Block: tx.Block, Token0AmountUint64: amountA, Token1AmountUint64: amountB, }, nil } } else { if exactIn { return &TxSignal{ TxHash: tx.Signatures[0].String(), Label: "raydiumlaunchlab", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(amountA), Token1Amount: formatSolAmount(amountB), Program: "RaydiumLaunchLab", Event: "sell", IsToken2022: false, IsMayhemMode: false, ExactSOL: false, Block: tx.Block, Token0AmountUint64: amountA, Token1AmountUint64: amountB, }, nil } else { return &TxSignal{ TxHash: tx.Signatures[0].String(), Label: "raydiumlaunchlab", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(amountB), Token1Amount: formatSolAmount(amountA), Program: "RaydiumLaunchLab", Event: "sell", IsToken2022: false, IsMayhemMode: false, ExactSOL: true, Block: tx.Block, Token0AmountUint64: amountB, Token1AmountUint64: amountA, }, nil } } }