2025-11-20 17:56:45 +08:00
|
|
|
package pump_parser
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
"github.com/shopspring/decimal"
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-21 12:01:44 +08:00
|
|
|
func systemParser(tx *Tx, instruction Instruction, _ InnerInstructions, offset [2]uint) ([2]uint, error) {
|
|
|
|
|
|
|
|
|
|
result := tx.rawTx
|
|
|
|
|
if !result.accountList[instruction.ProgramIDIndex].Equals(systemProgram) {
|
2025-11-20 17:56:45 +08:00
|
|
|
return increaseOffset(offset), fmt.Errorf("system program instruction not found, block: %d, tx: %s, outerIndex: %d, innerIndex: %d", result.Slot, result.TxHash(), offset[0], offset[1])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decode := instruction.Data
|
|
|
|
|
discriminator := binary.LittleEndian.Uint32(decode[0:4])
|
|
|
|
|
|
|
|
|
|
switch discriminator {
|
|
|
|
|
case transferDiscriminator:
|
|
|
|
|
return TransferParser(result, instruction, offset, tx, decode[4:])
|
|
|
|
|
default:
|
|
|
|
|
return increaseOffset(offset), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TransferParser(result *RawTx, instruction Instruction, offset [2]uint, tx *Tx, decodeData []byte) ([2]uint, error) {
|
|
|
|
|
if len(decodeData) < 8 {
|
|
|
|
|
return increaseOffset(offset), nil
|
|
|
|
|
}
|
|
|
|
|
var lamports uint64 = binary.LittleEndian.Uint64(decodeData)
|
|
|
|
|
|
2026-01-05 11:46:54 +08:00
|
|
|
from := result.accountList[result.Transaction.Message.Instructions[offset[0]].Accounts[0]]
|
2025-11-20 17:56:45 +08:00
|
|
|
to := result.accountList[instruction.Accounts[1]]
|
|
|
|
|
|
2026-01-05 11:46:54 +08:00
|
|
|
if offset[1] == 0 {
|
|
|
|
|
tx.Transfer = append(tx.Transfer, SolTransfer{
|
|
|
|
|
From: from,
|
|
|
|
|
To: to,
|
|
|
|
|
Amount: decimal.NewFromInt(int64(lamports)), // solana decimals
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-11-20 17:56:45 +08:00
|
|
|
// load platform by to address
|
|
|
|
|
platform, ok := platformFeeAddresses[to]
|
|
|
|
|
if ok {
|
|
|
|
|
if tx.Platform != nil {
|
|
|
|
|
tx.Platform[platform] = platformInfo{
|
|
|
|
|
Platform: platform,
|
|
|
|
|
PlatformFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
tx.Platform = make(map[string]platformInfo)
|
|
|
|
|
tx.Platform[platform] = platformInfo{
|
|
|
|
|
Platform: platform,
|
|
|
|
|
PlatformFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if offset[1] == 0 {
|
|
|
|
|
// load mev agent by to address
|
|
|
|
|
mevAgent, ok := mevAgentFeeAddresses[to]
|
|
|
|
|
if !ok {
|
|
|
|
|
// mark it as unknown
|
|
|
|
|
mevAgent = MevAgentUnknown
|
|
|
|
|
}
|
|
|
|
|
if tx.MevAgent == nil {
|
|
|
|
|
tx.MevAgent = make(map[string]mevInfo)
|
|
|
|
|
}
|
|
|
|
|
tx.MevAgent[mevAgent] = mevInfo{
|
|
|
|
|
MevAgent: mevAgent,
|
|
|
|
|
MevAgentFee: decimal.NewFromInt(int64(lamports)).Div(decimal.NewFromInt(1e9)), // solana decimals
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return increaseOffset(offset), nil
|
|
|
|
|
}
|