From 17a3c9e89c36cd657ec39f4781dc38f181429e27 Mon Sep 17 00:00:00 2001 From: samlior Date: Mon, 23 Mar 2026 15:02:58 +0800 Subject: [PATCH] chore: support raydium launch lab create --- pkg/shreder/program_raydiumlaunchlab.go | 47 +++++++++++- pkg/shreder/txparser_test.go | 98 +++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 4 deletions(-) diff --git a/pkg/shreder/program_raydiumlaunchlab.go b/pkg/shreder/program_raydiumlaunchlab.go index 9b9dfcc..c348dd1 100644 --- a/pkg/shreder/program_raydiumlaunchlab.go +++ b/pkg/shreder/program_raydiumlaunchlab.go @@ -5,14 +5,17 @@ import ( "fmt" "github.com/gagliardetto/solana-go" + "github.com/shopspring/decimal" ) 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} + raydiumLaunchLabInitializeV2PoolDiscriminator = []byte{67, 153, 175, 39, 218, 16, 38, 32} + raydiumLaunchLabInitializeWithToken2022PoolDiscriminator = []byte{37, 190, 126, 222, 44, 154, 171, 17} + 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) { @@ -40,6 +43,10 @@ func parseRaydiumLaunchLabInstruction(tx VersionedTransaction, instructionIndex txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, false, true) } else if matchMethod(instruction.Data, raydiumLaunchLabSellExactOutDiscriminator) { txSignal, err = parseRaydiumLaunchLabSwap(tx, instruction, false, false) + } else if matchMethod(instruction.Data, raydiumLaunchLabInitializeV2PoolDiscriminator) { + txSignal, err = parseRaydiumLaunchLabCreate(tx, instruction, false) + } else if matchMethod(instruction.Data, raydiumLaunchLabInitializeWithToken2022PoolDiscriminator) { + txSignal, err = parseRaydiumLaunchLabCreate(tx, instruction, true) } if txSignal != nil { return TxSignalBatch{txSignal}, err @@ -47,6 +54,38 @@ func parseRaydiumLaunchLabInstruction(tx VersionedTransaction, instructionIndex return nil, err } +func parseRaydiumLaunchLabCreate(tx VersionedTransaction, instruction Instructions, isToken2022 bool) (*TxSignal, error) { + if len(instruction.Accounts) < 10 { + return nil, fmt.Errorf("accounts too short") + } + + mint, err := tx.GetAccount(int(instruction.Accounts[6])) + if err != nil { + return nil, err + } + creator, err := tx.GetAccount(int(instruction.Accounts[1])) + if err != nil { + return nil, err + } + + return &TxSignal{ + TxHash: tx.Signatures[0].String(), + Label: "raydiumlaunchlab", + Maker: creator.String(), + Token0Address: mint.String(), + Token1Address: wsolMint, + Token0Amount: decimal.Zero, + Token1Amount: decimal.Zero, + Program: "RaydiumLaunchLab", + Event: "create", + IsToken2022: isToken2022, + IsMayhemMode: false, + Block: tx.Block, + Token0AmountUint64: 0, + Token1AmountUint64: 0, + }, nil +} + func parseRaydiumLaunchLabSwap(tx VersionedTransaction, instruction Instructions, isBuy bool, exactIn bool) (*TxSignal, error) { if len(instruction.Accounts) < 10 { return nil, fmt.Errorf("accounts too short") diff --git a/pkg/shreder/txparser_test.go b/pkg/shreder/txparser_test.go index 07a1875..dfbb2a2 100644 --- a/pkg/shreder/txparser_test.go +++ b/pkg/shreder/txparser_test.go @@ -679,3 +679,101 @@ func TestParseRaydiumLaunchLabSellExactOut(t *testing.T) { t.Fatalf("expected ExactSOL true, got false") } } + +func TestParseRaydiumLaunchLabCreate(t *testing.T) { + rpcUrl := os.Getenv("SOL_RPC_URL") + if rpcUrl == "" { + t.Fatalf("SOL_RPC_URL is not set") + } + + client := rpc.New(rpcUrl) + ch := make(chan TxSignal) + closed := make(chan struct{}) + go func() { + ParseTransactionForSubscribe( + context.Background(), + getTransaction(t, client, "2qi4STgj33b1DydMKvtpqeSVwkcTJHww8ViX9ADMu2TaRz2uSGcVjgDyd9AELnn2N1ojSGy2qnM6uiXJc2vEcLmw"), + nil, + ch, + closed, + ) + }() + go func() { + <-closed + close(ch) + }() + signals := make([]TxSignal, 0) + for signal := range ch { + signals = append(signals, signal) + } + + if len(signals) == 0 { + t.Fatalf("expected at least 1 signal, got %d", len(signals)) + } + + signal := signals[0] + if signal.Label != "raydiumlaunchlab" { + t.Fatalf("expected raydiumlaunchlab signal, got %s", signal.Label) + } + if signal.Event != "create" { + t.Fatalf("expected create event, got %s", signal.Event) + } + if signal.Maker != "F9TNxWymThfvs4kVVmyaBqx8pjxpvP7kScNBqiczeY84" { + t.Fatalf("expected maker F9TNxWymThfvs4kVVmyaBqx8pjxpvP7kScNBqiczeY84, got %s", signal.Maker) + } + if signal.Token0Address != "5VvwdKsYUjPTNbEotwDcV48PQEfi42of7TzaLyaybonk" { + t.Fatalf("expected token0 address 5VvwdKsYUjPTNbEotwDcV48PQEfi42of7TzaLyaybonk, got %s", signal.Token0Address) + } + if signal.IsToken2022 { + t.Fatalf("expected IsToken2022 false, got true") + } +} + +func TestParseRaydiumLaunchLabCreate2(t *testing.T) { + rpcUrl := os.Getenv("SOL_RPC_URL") + if rpcUrl == "" { + t.Fatalf("SOL_RPC_URL is not set") + } + + client := rpc.New(rpcUrl) + ch := make(chan TxSignal) + closed := make(chan struct{}) + go func() { + ParseTransactionForSubscribe( + context.Background(), + getTransaction(t, client, "3ZofgvJ3vrNRnyGfAFwENSrDAHxVuXhqrL4svwctHuxZHnAengj5SHeEwPJiJFPXYaBcnfrUAk2V4368LVVSEP2W"), + nil, + ch, + closed, + ) + }() + go func() { + <-closed + close(ch) + }() + signals := make([]TxSignal, 0) + for signal := range ch { + signals = append(signals, signal) + } + + if len(signals) == 0 { + t.Fatalf("expected at least 1 signal, got %d", len(signals)) + } + + signal := signals[0] + if signal.Label != "raydiumlaunchlab" { + t.Fatalf("expected raydiumlaunchlab signal, got %s", signal.Label) + } + if signal.Event != "create" { + t.Fatalf("expected create event, got %s", signal.Event) + } + if signal.Maker != "7GhWwhaMgbKiRWxF93Bud6HnHMci6NCLTJyTxG8zFH51" { + t.Fatalf("expected maker 7GhWwhaMgbKiRWxF93Bud6HnHMci6NCLTJyTxG8zFH51, got %s", signal.Maker) + } + if signal.Token0Address != "GWeFeDVD75PVGHdLf7HrYJe2BYTiA8J3nVJXSqb4CpoU" { + t.Fatalf("expected token0 address GWeFeDVD75PVGHdLf7HrYJe2BYTiA8J3nVJXSqb4CpoU, got %s", signal.Token0Address) + } + if !signal.IsToken2022 { + t.Fatalf("expected IsToken2022 true, got false") + } +}