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 } func FromTx(tx *parser.Tx) []*Tx { var txs = make([]*Tx, 0, len(tx.Swaps)) mev, mevFee := tx.CheckMevAgent() for i, s := range tx.Swaps { var newTx *Tx platform, platformFee := tx.CheckPlatform(s) token0Program := s.BaseTokenProgram token0Address := s.BaseMint token0Decimals := s.BaseMintDecimals 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 token0Decimals = s.QuoteMintDecimals 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() newTx.AfterSignerToken0Balance = tx.GetSignerTokenBalanceAfterTx(token0Program, token0Address).Div(decimal.New(1, int32(token0Decimals))) } txs = append(txs, newTx) } return txs }