Files
pump-parser/tx.go

251 lines
5.6 KiB
Go
Raw Permalink Normal View History

2025-11-20 17:56:45 +08:00
package pump_parser
import (
"github.com/gagliardetto/solana-go"
"github.com/mr-tron/base58"
"github.com/shopspring/decimal"
)
type Swap struct {
Program string
Event string
Pool solana.PublicKey
BaseMint solana.PublicKey
QuoteMint solana.PublicKey
BaseTokenProgram solana.PublicKey
QuoteTokenProgram solana.PublicKey
Creator solana.PublicKey
BaseMintDecimals uint8
QuoteMintDecimals uint8
User solana.PublicKey
BaseAmount decimal.Decimal
QuoteAmount decimal.Decimal
BaseReserve decimal.Decimal
QuoteReserve decimal.Decimal
Mayhem bool
UserBaseBalance decimal.Decimal
UserQuoteBalance decimal.Decimal
EntryContract solana.PublicKey
//For meteora dlmm
StartBinId int32
EndBinId int32
2026-01-15 17:44:39 +08:00
BinChanges []DlmmBinLiquidityChange
}
type DlmmBinLiquidityChange struct {
BinId int32
AmountX decimal.Decimal
AmountY decimal.Decimal
BpsToRemove uint16
2025-11-20 17:56:45 +08:00
}
type platformInfo struct {
Platform string
PlatformFee decimal.Decimal
}
type mevInfo struct {
MevAgent string
MevAgentFee decimal.Decimal
}
2026-01-05 11:46:54 +08:00
type SolTransfer struct {
From solana.PublicKey
To solana.PublicKey
Amount decimal.Decimal
}
2025-11-20 17:56:45 +08:00
type Tx struct {
2026-01-05 11:46:54 +08:00
rawTx *RawTx
2026-02-02 14:13:00 +08:00
Vote bool
2026-01-05 11:46:54 +08:00
Signer solana.PublicKey
Err interface{} `json:"err,omitempty"`
Swaps []Swap `json:"swaps,omitempty"`
SolTransfer []SolTransfer `json:"sol_transfer,omitempty"`
Block uint64 `json:"block"`
BlockIndex uint64 `json:"index"`
TxHash *[64]byte `json:"-"`
BlockAt int64 `json:"block_at"`
CuFee decimal.Decimal `json:"cu_fee"`
2025-11-20 17:56:45 +08:00
cachedTxHash string
Platform map[string]platformInfo `json:"platform"`
MevAgent map[string]mevInfo ` json:"tx_mev_agent"`
CUPrice decimal.Decimal ` json:"tx_cu_price"`
BeforeSolBalance decimal.Decimal `json:"-"`
AfterSOLBalance decimal.Decimal `json:"after_sol_balance"`
2025-11-21 12:01:44 +08:00
// update tokenInfo
Token map[solana.PublicKey]TokenMeta `gorm:"-"`
// todo pool info ??
}
2026-02-02 14:13:00 +08:00
func (tx *Tx) GetRawTx() *RawTx {
return tx.rawTx
}
2025-11-21 12:01:44 +08:00
func (tx *Tx) SetRawTx(t *RawTx) {
tx.rawTx = t
}
func (tx *Tx) GetSignerTokenBalanceAfterTx(tokenProgram, tokenMint solana.PublicKey) decimal.Decimal {
return GetTokenBalanceAfterTx(tx.rawTx, 0, tokenProgram, tokenMint)
2025-11-20 17:56:45 +08:00
}
type TokenMeta struct {
2025-11-21 12:01:44 +08:00
Mint solana.PublicKey `json:"address"`
2025-11-20 17:56:45 +08:00
TokenProgram solana.PublicKey `json:"token_program"`
2025-11-21 12:01:44 +08:00
Decimals uint8 `json:"decimals"`
2025-11-20 17:56:45 +08:00
2025-11-21 12:01:44 +08:00
Name string
Symbol string
Url string
2025-11-20 17:56:45 +08:00
2025-11-21 12:01:44 +08:00
TotalSupply *decimal.Decimal
2025-11-20 17:56:45 +08:00
}
func (tx *Tx) GetTxHash() string {
if tx.cachedTxHash != "" {
return tx.cachedTxHash
}
if tx.TxHash == nil {
return ""
}
tx.cachedTxHash = base58.Encode(tx.TxHash[:])
return tx.cachedTxHash
}
2025-11-21 12:01:44 +08:00
func (tx *Tx) CheckPlatform(swap Swap) (string, decimal.Decimal) {
2025-11-20 17:56:45 +08:00
// hasSolProgramRaydiumLaunchLabBonk
2025-11-21 12:01:44 +08:00
rawTx := tx.rawTx
2025-11-20 17:56:45 +08:00
var platform string
var platformFee decimal.Decimal
if len(tx.Platform) == 0 {
return PlatformNone, decimal.Zero
}
for p, info := range tx.Platform {
platform = p
platformFee = info.PlatformFee
break
}
2026-02-02 14:13:00 +08:00
if swap.Event == "buy" {
switch swap.Program {
case SolProgramRaydiumLaunchLabBonk:
for _, p := range tx.Platform {
switch p.Platform {
case PlatformAxiom:
if !checkBonkAxiomBuy(rawTx) {
platform = PlatformFake
}
case PlatformGMGN:
if !checkBonkGmgnBuy(rawTx) {
platform = PlatformFake
}
2025-11-20 17:56:45 +08:00
}
2026-02-02 14:13:00 +08:00
}
}
if swap.Program == SolProgramRaydiumLaunchLabBonk {
for _, p := range tx.Platform {
switch p.Platform {
case PlatformAxiom:
if !checkPumpFunAxiomBuy(rawTx) {
platform = PlatformFake
}
case PlatformGMGN:
if !checkPumpFunGmgnBuy(rawTx) {
platform = PlatformFake
}
2025-11-20 17:56:45 +08:00
}
}
}
}
if platform != "" &&
platform != PlatformFake {
if (swap.QuoteMint.Equals(wSolMint) || swap.QuoteMint.IsZero()) &&
platformFee.LessThan(swap.QuoteAmount.Div(decimal.New(1, int32(swap.QuoteMintDecimals))).Div(decimal.NewFromInt(10000)).Mul(decimal.NewFromInt(9))) {
platform = PlatformFake
} else if swap.BaseMint.Equals(wSolMint) &&
platformFee.LessThan(swap.QuoteAmount.Div(decimal.New(1, int32(swap.QuoteMintDecimals))).Div(decimal.NewFromInt(10000)).Mul(decimal.NewFromInt(9))) {
platform = PlatformFake
}
}
if platform == "" {
platform = PlatformNone
}
return platform, platformFee
}
func (tx *Tx) CheckMevAgent() (string, decimal.Decimal) {
var mevAgent = MevAgentUnknown
var mevAgentFee = decimal.Zero
for m, info := range tx.MevAgent {
if len(tx.MevAgent) > 1 && info.MevAgent == MevAgentUnknown {
continue
}
mevAgent = m
mevAgentFee = info.MevAgentFee
break
}
if len(tx.MevAgent) == 0 && mevAgent == MevAgentUnknown {
// set the mev agent to none if the platform does not exist
return "", decimal.Zero
}
return mevAgent, mevAgentFee
}
func (s Swap) CheckEntryContract() string {
name, ok := entryContractAddresses[s.EntryContract]
if ok {
return name
}
return EntryContractUnknown
}
2025-12-31 16:53:39 +08:00
2026-02-02 14:13:00 +08:00
func (tx *Tx) LoadAfterSOLBalance(swap Swap) decimal.Decimal {
if swap.User.Equals(tx.Signer) {
return tx.AfterSOLBalance
}
found := false
makerIndex := 0
for i, account := range tx.rawTx.getAccountList() {
if account == swap.User {
found = true
makerIndex = i
break
}
}
if found && makerIndex < len(tx.rawTx.Meta.PostBalances) {
return decimal.NewFromInt(
int64(tx.rawTx.Meta.PostBalances[makerIndex]),
).Div(decimal.NewFromInt(1000000000)) // sol decimals
}
return decimal.Zero
}
2025-12-31 16:53:39 +08:00
func (s Swap) CheckEntryContractV2() string {
name, ok := entryContractAddresses[s.EntryContract]
if ok {
return name
}
return s.EntryContract.String()
}