chore: support pump create

This commit is contained in:
2026-03-23 15:43:08 +08:00
parent 17a3c9e89c
commit 21eba4264f
3 changed files with 163 additions and 23 deletions

View File

@@ -34,10 +34,18 @@ type pumpCreateCoinV2Args struct {
Uri string Uri string
Creator solana.PublicKey Creator solana.PublicKey
IsMayhemMode bool IsMayhemMode bool
IsCashbackEnabled bool
}
type legacyPumpCreateCoinV2Args struct {
Name string
Symbol string
Uri string
Creator solana.PublicKey
IsMayhemMode bool
} }
func parsePumpInstruction(msg VersionedTransaction, instructionIndex int) (TxSignalBatch, error) { func parsePumpInstruction(msg VersionedTransaction, instructionIndex int) (TxSignalBatch, error) {
instruction := msg.Instructions[instructionIndex] instruction := msg.Instructions[instructionIndex]
if len(instruction.Data) < 8 { if len(instruction.Data) < 8 {
return nil, fmt.Errorf("data is empty") return nil, fmt.Errorf("data is empty")
@@ -114,8 +122,19 @@ func parsePumpCreateV2(tx VersionedTransaction, instruction Instructions) (*TxSi
var args pumpCreateCoinV2Args var args pumpCreateCoinV2Args
if err := borsh.Deserialize(&args, instruction.Data[8:]); err != nil { if err := borsh.Deserialize(&args, instruction.Data[8:]); err != nil {
var legacyArgs legacyPumpCreateCoinV2Args
if err := borsh.Deserialize(&legacyArgs, instruction.Data[8:]); err != nil {
return nil, fmt.Errorf("failed to parse create coin v2 args: %w", err) return nil, fmt.Errorf("failed to parse create coin v2 args: %w", err)
} }
args = pumpCreateCoinV2Args{
Name: legacyArgs.Name,
Symbol: legacyArgs.Symbol,
Uri: legacyArgs.Uri,
Creator: legacyArgs.Creator,
IsMayhemMode: legacyArgs.IsMayhemMode,
IsCashbackEnabled: false,
}
}
return &TxSignal{ return &TxSignal{
TxHash: tx.Signatures[0].String(), TxHash: tx.Signatures[0].String(),
@@ -129,6 +148,7 @@ func parsePumpCreateV2(tx VersionedTransaction, instruction Instructions) (*TxSi
Event: "create", Event: "create",
IsToken2022: tokenProgramKey.String() != tokenProgram, IsToken2022: tokenProgramKey.String() != tokenProgram,
IsMayhemMode: args.IsMayhemMode, IsMayhemMode: args.IsMayhemMode,
IsCashbackEnabled: args.IsCashbackEnabled,
Block: tx.Block, Block: tx.Block,
Token0AmountUint64: 0, Token0AmountUint64: 0,
Token1AmountUint64: 0, Token1AmountUint64: 0,

View File

@@ -44,6 +44,7 @@ type TxSignal struct {
IsProcessed bool `json:"is_processed"` IsProcessed bool `json:"is_processed"`
IsToken2022 bool `json:"is_token2022"` IsToken2022 bool `json:"is_token2022"`
IsMayhemMode bool `json:"is_mayhem_mode"` IsMayhemMode bool `json:"is_mayhem_mode"`
IsCashbackEnabled bool `json:"is_cashback_enabled"`
CUPrice decimal.Decimal `json:"cu_price"` CUPrice decimal.Decimal `json:"cu_price"`
CULimit uint32 `json:"cu_limit"` CULimit uint32 `json:"cu_limit"`
SWQoSAgent string `json:"swqos_agent"` SWQoSAgent string `json:"swqos_agent"`

View File

@@ -777,3 +777,122 @@ func TestParseRaydiumLaunchLabCreate2(t *testing.T) {
t.Fatalf("expected IsToken2022 true, got false") t.Fatalf("expected IsToken2022 true, got false")
} }
} }
func manuallyLoadAddressTable(t *testing.T, client *rpc.Client, tablePubkey solana.PublicKey) *AddressTables {
loader := NewAddressTables(client, false)
table, err := loader.loadAddressTable(tablePubkey)
if err != nil {
t.Fatalf("failed to load address table: %s", err)
}
loader.tables.Add(tablePubkey, &TableInfo{
addresses: table,
})
return loader
}
func TestParsePumpCreate(t *testing.T) {
rpcUrl := os.Getenv("SOL_RPC_URL")
if rpcUrl == "" {
t.Fatalf("SOL_RPC_URL is not set")
}
client := rpc.New(rpcUrl)
loader := manuallyLoadAddressTable(t, client, solana.MustPublicKeyFromBase58("AXVvmhWaaPtV52jqYuTNqp1xRrkbxhfJfeHQKxq5cbvZ"))
ch := make(chan TxSignal)
closed := make(chan struct{})
go func() {
ParseTransactionForSubscribe(
context.Background(),
getTransaction(t, client, "3vUAHpBUoxeoZheo9m3XmufNUWmJWRAN4xZjSqDos71GL6tCKSTmJV6YeMS5XdVAbRAfqQi1rPusjbmEhoam4x9Y"),
loader,
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 != "pump" {
t.Fatalf("expected pump signal, got %s", signal.Label)
}
if signal.Event != "create" {
t.Fatalf("expected create event, got %s", signal.Event)
}
if signal.Maker != "8oVJLE69qH1i5jotFABcCoaPS38DAyZ7djRg6uuD3Cb7" {
t.Fatalf("expected maker 8oVJLE69qH1i5jotFABcCoaPS38DAyZ7djRg6uuD3Cb7, got %s", signal.Maker)
}
if signal.Token0Address != "AtaWsdyfcANLsHNdpYJyFdNvwSQnUzvhRN2MCCP9pump" {
t.Fatalf("expected token0 address AtaWsdyfcANLsHNdpYJyFdNvwSQnUzvhRN2MCCP9pump, got %s", signal.Token0Address)
}
if !signal.IsToken2022 {
t.Fatalf("expected IsToken2022 true, got false")
}
if signal.IsCashbackEnabled {
t.Fatalf("expected IsCashbackEnabled true, got false")
}
}
func TestParsePumpCreate2(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, "3EKKjtNFzhtQaA9GyPt5UJHLr5mWT2XodaxWoenUrcaPpN8BKm84ATVapdUJcb9sJVFyS4iKD9spGBKfqkSFutea"),
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 != "pump" {
t.Fatalf("expected pump signal, got %s", signal.Label)
}
if signal.Event != "create" {
t.Fatalf("expected create event, got %s", signal.Event)
}
if signal.Maker != "5mGqXMqUbJzxQ9aqbBttB4JUfAMqceSTmrtpt6RuPXdC" {
t.Fatalf("expected maker 5mGqXMqUbJzxQ9aqbBttB4JUfAMqceSTmrtpt6RuPXdC, got %s", signal.Maker)
}
if signal.Token0Address != "J9Hqi5VddcTNJ2F5EyxSZxC2JpJeymfJXjLhsCVPZpna" {
t.Fatalf("expected token0 address J9Hqi5VddcTNJ2F5EyxSZxC2JpJeymfJXjLhsCVPZpna, got %s", signal.Token0Address)
}
if !signal.IsToken2022 {
t.Fatalf("expected IsToken2022 true, got false")
}
if signal.IsCashbackEnabled {
t.Fatalf("expected IsCashbackEnabled true, got false")
}
}