80 lines
2.5 KiB
Go
80 lines
2.5 KiB
Go
package pump_parser
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/gagliardetto/solana-go"
|
|
)
|
|
|
|
var (
|
|
WSOLString = "So11111111111111111111111111111111111111112"
|
|
WSOL = solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112")
|
|
USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
|
)
|
|
|
|
const (
|
|
SOLDecimals = 9
|
|
)
|
|
|
|
var (
|
|
InstructionIgnoredError = errors.New("instruction ignored")
|
|
)
|
|
|
|
type swapParser func(tx *Tx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error)
|
|
type actionParser func(tx *Tx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([2]uint, error)
|
|
|
|
func getInnerInstructions(innerInstructions InnerInstructions, offset uint) ([]Instruction, error) {
|
|
var inners []Instruction
|
|
var prefixLen = offset
|
|
if prefixLen > uint(len(innerInstructions.Instructions)) {
|
|
return nil, fmt.Errorf("error inner instruction index out of range")
|
|
}
|
|
if prefixLen == 0 {
|
|
inners = innerInstructions.Instructions
|
|
} else {
|
|
inners = innerInstructions.Instructions[prefixLen:]
|
|
}
|
|
return inners, nil
|
|
}
|
|
|
|
func parseTokenTransfer(tx *RawTx, instr Instruction) (from solana.PublicKey, to solana.PublicKey, amount uint64, err error) {
|
|
if len(instr.Accounts) < 3 {
|
|
return solana.PublicKey{}, solana.PublicKey{}, 0, fmt.Errorf("not enough accounts for token transfer instruction")
|
|
}
|
|
programAccount := tx.accountList[instr.ProgramIDIndex]
|
|
if !programAccount.Equals(solana.TokenProgramID) && !programAccount.Equals(solana.Token2022ProgramID) {
|
|
return solana.PublicKey{}, solana.PublicKey{}, 0, fmt.Errorf("not a token program instruction")
|
|
}
|
|
if len(instr.Data) < 9 {
|
|
return solana.PublicKey{}, solana.PublicKey{}, 0, fmt.Errorf("invalid data length for token transfer instruction")
|
|
}
|
|
method := instr.Data[0]
|
|
if method != 3 && method != 12 { // Transfer instruction
|
|
return solana.PublicKey{}, solana.PublicKey{}, 0, fmt.Errorf("not a token transfer instruction")
|
|
}
|
|
if method == 3 {
|
|
// Transfer
|
|
amount = binary.LittleEndian.Uint64(instr.Data[1:9])
|
|
from = tx.accountList[instr.Accounts[0]]
|
|
to = tx.accountList[instr.Accounts[1]]
|
|
} else {
|
|
// TransferChecked
|
|
amount = binary.LittleEndian.Uint64(instr.Data[1:9])
|
|
from = tx.accountList[instr.Accounts[0]]
|
|
to = tx.accountList[instr.Accounts[2]]
|
|
}
|
|
|
|
return from, to, amount, nil
|
|
}
|
|
|
|
func isMayhemPump(feeAccount solana.PublicKey) bool {
|
|
for _, mayhemFeeAccount := range mayhemFeeAccounts {
|
|
if feeAccount.Equals(mayhemFeeAccount) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|