package pump_parser import ( "encoding/binary" "testing" "github.com/gagliardetto/solana-go" "github.com/shopspring/decimal" ) func transferInstructionData(amount uint64) solana.Base58 { data := make([]byte, 9) data[0] = 3 binary.LittleEndian.PutUint64(data[1:], amount) return solana.Base58(data) } func TestRaydiumV4SwapV2ParserAllowsTrailingReadonlyAccounts(t *testing.T) { t.Parallel() accountList := make([]solana.PublicKey, 32) for i := range accountList { accountList[i] = testPublicKey(byte(i + 1)) } accountList[0] = solana.TokenProgramID accountList[8] = raydiumV4Program accountList[20] = testPublicKey(200) accountList[21] = testPublicKey(201) accountList[22] = testPublicKey(202) outerInstruction := Instruction{ProgramIDIndex: 20} swapInstruction := Instruction{ Accounts: []int{0, 1, 2, 3, 4, 5, 6, 7, 8}, ProgramIDIndex: 8, Data: solana.Base58([]byte{raydiumV4SwapBaseInV2Discriminator}), } innerInstructions := InnerInstructions{ Index: 0, Instructions: []Instruction{ swapInstruction, { Accounts: []int{5, 4, 7}, ProgramIDIndex: 0, Data: transferInstructionData(55), }, { Accounts: []int{3, 6, 2}, ProgramIDIndex: 0, Data: transferInstructionData(42), }, }, } rawTx := &RawTx{ accountList: accountList, Meta: Meta{ PostTokenBalances: []TokenBalance{ { AccountIndex: 3, MintAccount: accountList[21], ProgramIDAccount: solana.TokenProgramID, UITokenAmount: UITokenAmount{ Amount: "1000", Decimals: 6, }, }, { AccountIndex: 4, MintAccount: accountList[22], ProgramIDAccount: solana.TokenProgramID, UITokenAmount: UITokenAmount{ Amount: "2000", Decimals: 9, }, }, { AccountIndex: 5, MintAccount: accountList[22], ProgramIDAccount: solana.TokenProgramID, UITokenAmount: UITokenAmount{ Amount: "300", Decimals: 9, }, }, { AccountIndex: 6, MintAccount: accountList[21], ProgramIDAccount: solana.TokenProgramID, UITokenAmount: UITokenAmount{ Amount: "400", Decimals: 6, }, }, }, }, Transaction: Transaction{ Message: Message{ Instructions: []Instruction{outerInstruction}, }, }, } tx := &Tx{rawTx: rawTx} swaps, nextOffset, err := raydiumv4SwapV2Parser(tx, swapInstruction, innerInstructions, [2]uint{0, 1}) if err != nil { t.Fatalf("raydiumv4SwapV2Parser() error = %v", err) } if len(swaps) != 1 { t.Fatalf("raydiumv4SwapV2Parser() swaps len = %d, want 1", len(swaps)) } if nextOffset != [2]uint{0, 4} { t.Fatalf("raydiumv4SwapV2Parser() nextOffset = %v, want [0 4]", nextOffset) } swap := swaps[0] if swap.Event != "buy" { t.Fatalf("swap.Event = %q, want %q", swap.Event, "buy") } if !swap.Pool.Equals(accountList[1]) { t.Fatalf("swap.Pool = %s, want %s", swap.Pool, accountList[1]) } if !swap.User.Equals(accountList[7]) { t.Fatalf("swap.User = %s, want %s", swap.User, accountList[7]) } if !swap.EntryContract.Equals(accountList[20]) { t.Fatalf("swap.EntryContract = %s, want %s", swap.EntryContract, accountList[20]) } if !swap.BaseAmount.Equal(decimal.NewFromInt(42)) { t.Fatalf("swap.BaseAmount = %s, want 42", swap.BaseAmount) } if !swap.QuoteAmount.Equal(decimal.NewFromInt(55)) { t.Fatalf("swap.QuoteAmount = %s, want 55", swap.QuoteAmount) } }