Files
pump-parser/example/tx.go

232 lines
8.6 KiB
Go
Raw Normal View History

2025-11-20 17:56:45 +08:00
package example
import (
"time"
"github.com/gagliardetto/solana-go"
"github.com/jackc/pgtype"
"github.com/mr-tron/base58"
"github.com/shopspring/decimal"
parser "github.com/thloyi/pump-parser"
)
type Tx struct {
Err interface{} `json:"err,omitempty" gorm:"-"`
BondingCurve string `json:"bonding_curve" gorm:"-"`
PairAddress string `json:"pair_address"`
Maker string `json:"maker"`
Token0Address string `json:"token0_address"`
Token0Program string `json:"token0_program" gorm:"-"`
Token0Decimals uint8 `json:"token0_decimals" gorm:"-"`
Token1Address string `json:"token1_address"`
Token0Amount decimal.Decimal `json:"token0Amount" gorm:"column:token0_amount;type:numeric"`
Token1Amount decimal.Decimal `json:"token1Amount" gorm:"column:token1_amount;type:numeric"`
PriceUsd decimal.Decimal `json:"price_usd" gorm:"column:price_usd;type:numeric"`
AmountUsd decimal.Decimal `json:"amount_usd" gorm:"column:amount_usd;type:numeric"`
Block uint64 `json:"block"`
BlockIndex uint64 `json:"index"`
Event string `json:"event"`
CachedTxHash string `json:"tx_hash" gorm:"column:tx_hash"`
txHash *[64]byte `gorm:"-"`
TxIndex uint64 `json:"topic_index"`
Program string `json:"program"`
BlockAt pgtype.Timestamptz `gorm:"column:block_at;default:NULL" json:"block_at"`
CreatedAt *pgtype.Timestamptz `gorm:"autoCreateTime" json:"-"`
TotalSupply string `gorm:"total_supply"`
AfterReserve0 string `gorm:"after_reserve0"`
AfterReserve1 string `gorm:"after_reserve1"`
PositionChange int64 `gorm:"position_change"`
QuoteIsToken0 bool `gorm:"-"`
CurrentPrice decimal.Decimal `gorm:"-"`
TokenCreator string `gorm:"-"`
Platform string `gorm:"column:tx_platform;type:platform;default:'none'" json:"platform"`
MevAgent string `gorm:"column:tx_mev_agent;type:mev_agent;default:'none'" json:"tx_mev_agent"`
MevAgentFee decimal.Decimal `gorm:"column:tx_mev_agent_fee;type:numeric" json:"tx_mev_agent_fee"`
CUPrice decimal.Decimal `gorm:"column:tx_cu_price;type:numeric" json:"tx_cu_price"`
PlatformFee decimal.Decimal `gorm:"-"`
AfterSignerToken0Balance decimal.Decimal `gorm:"-" json:"-"`
BeforeSolBalance decimal.Decimal `gorm:"-" json:"-"`
AfterSOLBalance decimal.Decimal `gorm:"column:after_sol_balance;type:numeric" json:"after_sol_balance"`
EntryContract string `gorm:"column:tx_entry_contract;type:entry_contract;default:'none'" json:"tx_entry_contract"`
Mayhem bool
}
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 FromTx(tx *parser.Tx) []*Tx {
var txs = make([]*Tx, 0, len(tx.Swaps))
2025-11-20 17:56:45 +08:00
mev, mevFee := tx.CheckMevAgent()
for i, s := range tx.Swaps {
var newTx *Tx
2025-11-21 12:01:44 +08:00
platform, platformFee := tx.CheckPlatform(s)
2025-11-20 17:56:45 +08:00
token0Program := s.BaseTokenProgram
token0Address := s.BaseMint
2025-11-21 12:01:44 +08:00
token0Decimals := s.BaseMintDecimals
2025-11-20 17:56:45 +08:00
if s.Program == "Pump" {
newTx = &Tx{
Err: nil,
BondingCurve: s.Pool.String(),
//PairAddress: s.Pool.String(),
Maker: s.User.String(),
Token0Address: s.BaseMint.String(),
Token0Program: s.BaseTokenProgram.String(),
Token0Decimals: s.BaseMintDecimals,
Token1Address: "",
Token0Amount: s.BaseAmount.Div(decimal.NewFromInt(1e6)),
Token1Amount: s.QuoteAmount.Div(decimal.NewFromInt(1e9)),
Block: tx.Block,
BlockIndex: tx.BlockIndex,
Event: s.Event,
CachedTxHash: "",
txHash: tx.TxHash,
TxIndex: uint64(i),
Program: s.Program,
BlockAt: pgtype.Timestamptz{
Time: time.Unix(tx.BlockAt, 0),
},
//CreatedAt: nil,
TotalSupply: "1000000000",
AfterReserve0: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(),
AfterReserve1: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(),
QuoteIsToken0: false,
// CurrentPrice: decimal.Decimal{},
TokenCreator: s.Creator.String(),
Platform: platform,
PlatformFee: platformFee,
MevAgent: mev,
MevAgentFee: mevFee,
CUPrice: tx.CUPrice,
AfterSignerToken0Balance: s.UserBaseBalance.Div(decimal.New(1, int32(s.BaseMintDecimals))),
BeforeSolBalance: tx.BeforeSolBalance,
AfterSOLBalance: tx.AfterSOLBalance,
EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem,
}
} else if s.Program == "PumpAMM" {
if s.BaseMint.Equals(solana.WrappedSol) {
eventName := s.Event
if s.Event == "buy" {
eventName = "sell"
} else if s.Event == "sell" {
eventName = "buy"
}
token0Program = s.QuoteTokenProgram
token0Address = s.QuoteMint
2025-11-21 12:01:44 +08:00
token0Decimals = s.QuoteMintDecimals
2025-11-20 17:56:45 +08:00
newTx = &Tx{
Err: nil,
//BondingCurve: s.Pool.String(),
PairAddress: s.Pool.String(),
Maker: s.User.String(),
Token1Address: s.BaseMint.String(),
Token0Program: s.QuoteTokenProgram.String(),
Token0Decimals: s.QuoteMintDecimals,
Token0Address: s.QuoteMint.String(),
Token1Amount: s.BaseAmount.Div(decimal.New(1, int32(s.BaseMintDecimals))),
Token0Amount: s.QuoteAmount.Div(decimal.New(1, int32(s.QuoteMintDecimals))),
Block: tx.Block,
BlockIndex: tx.BlockIndex,
Event: eventName,
CachedTxHash: "",
txHash: tx.TxHash,
TxIndex: uint64(i),
Program: s.Program,
BlockAt: pgtype.Timestamptz{
Time: time.Unix(tx.BlockAt, 0),
},
//CreatedAt: nil,
TotalSupply: "1000000000",
AfterReserve1: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(),
AfterReserve0: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(),
QuoteIsToken0: true,
// CurrentPrice: decimal.Decimal{},
TokenCreator: s.Creator.String(),
Platform: platform,
PlatformFee: platformFee,
MevAgent: mev,
MevAgentFee: mevFee,
CUPrice: tx.CUPrice,
AfterSignerToken0Balance: s.UserQuoteBalance.Div(decimal.New(1, int32(s.QuoteMintDecimals))),
BeforeSolBalance: tx.BeforeSolBalance,
AfterSOLBalance: tx.AfterSOLBalance,
EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem,
}
} else {
newTx = &Tx{
Err: nil,
//BondingCurve: s.Pool.String(),
PairAddress: s.Pool.String(),
Maker: s.User.String(),
Token0Address: s.BaseMint.String(),
Token0Program: s.BaseTokenProgram.String(),
Token0Decimals: s.BaseMintDecimals,
Token1Address: s.QuoteMint.String(),
Token0Amount: s.BaseAmount.Div(decimal.New(1, int32(s.BaseMintDecimals))),
Token1Amount: s.QuoteAmount.Div(decimal.New(1, int32(s.QuoteMintDecimals))),
Block: tx.Block,
BlockIndex: tx.BlockIndex,
Event: s.Event,
CachedTxHash: "",
txHash: tx.TxHash,
TxIndex: uint64(i),
Program: s.Program,
BlockAt: pgtype.Timestamptz{
Time: time.Unix(tx.BlockAt, 0),
},
//CreatedAt: nil,
TotalSupply: "1000000000",
AfterReserve0: s.BaseReserve.Div(decimal.New(1, int32(s.BaseMintDecimals))).String(),
AfterReserve1: s.QuoteReserve.Div(decimal.New(1, int32(s.QuoteMintDecimals))).String(),
QuoteIsToken0: false,
// CurrentPrice: decimal.Decimal{},
TokenCreator: s.Creator.String(),
Platform: platform,
PlatformFee: platformFee,
MevAgent: mev,
MevAgentFee: mevFee,
CUPrice: tx.CUPrice,
AfterSignerToken0Balance: s.UserBaseBalance.Div(decimal.New(1, int32(s.BaseMintDecimals))),
BeforeSolBalance: tx.BeforeSolBalance,
AfterSOLBalance: tx.AfterSOLBalance,
EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem,
}
}
}
if newTx == nil {
continue
}
if newTx.Maker == "HV1KXxWFaSeriyFvXyx48FqG9BoFbfinB8njCJonqP7K" && newTx.EntryContract == "oKXAggregatorV2" {
newTx.Maker = tx.Signer.String()
2025-11-21 12:01:44 +08:00
newTx.AfterSignerToken0Balance = tx.GetSignerTokenBalanceAfterTx(token0Program, token0Address).Div(decimal.New(1, int32(token0Decimals)))
2025-11-20 17:56:45 +08:00
}
txs = append(txs, newTx)
}
return txs
}