Compare commits

...

5 Commits

Author SHA1 Message Date
cachalots
972ddc7960 IsCashbackCoin 2026-02-27 02:10:12 +08:00
bcd442195c chore: support IsCashbackEnabled 2026-02-27 01:43:07 +08:00
0633707142 chore: add trojan fee addresses 2026-02-26 15:19:57 +08:00
8e49f01054 must to next inner at least 2026-02-21 09:29:28 +08:00
thloyi
62cc64a90a fix from rpc ComputeUnitsConsumed 2026-02-12 10:43:30 +08:00
9 changed files with 32 additions and 12 deletions

View File

@@ -39,6 +39,8 @@ var platformFeeAddresses = map[solana.PublicKey]string{
solana.MustPublicKeyFromBase58("F4hJ3Ee3c5UuaorKAMfELBjYCjiiLH75haZTKqTywRP3"): PlatformBullX, solana.MustPublicKeyFromBase58("F4hJ3Ee3c5UuaorKAMfELBjYCjiiLH75haZTKqTywRP3"): PlatformBullX,
solana.MustPublicKeyFromBase58("47hEzz83VFR23rLTEeVm9A7eFzjJwjvdupPPmX3cePqF"): PlatformBanana, solana.MustPublicKeyFromBase58("47hEzz83VFR23rLTEeVm9A7eFzjJwjvdupPPmX3cePqF"): PlatformBanana,
solana.MustPublicKeyFromBase58("9yMwSPk9mrXSN7yDHUuZurAh1sjbJsfpUqjZ7SvVtdco"): PlatformTrojan, solana.MustPublicKeyFromBase58("9yMwSPk9mrXSN7yDHUuZurAh1sjbJsfpUqjZ7SvVtdco"): PlatformTrojan,
solana.MustPublicKeyFromBase58("92Med3qeK7duC5iiYsHX38H2f2twJfRsSx93oNrza2VH"): PlatformTrojan,
solana.MustPublicKeyFromBase58("65gDv7pZQCZELsNpNYSFEBtNFpWZAbxmRFB6BGMqFkHH"): PlatformTrojan,
solana.MustPublicKeyFromBase58("4mih95RmBqfHYvEfqq6uGGLp1Fr3gVS3VNSEa3JVRfQK"): PlatformRaybot, solana.MustPublicKeyFromBase58("4mih95RmBqfHYvEfqq6uGGLp1Fr3gVS3VNSEa3JVRfQK"): PlatformRaybot,
solana.MustPublicKeyFromBase58("3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N"): PlatformMoonshot, solana.MustPublicKeyFromBase58("3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N"): PlatformMoonshot,
solana.MustPublicKeyFromBase58("3kxSQybWEeQZsMuNWMRJH4TxrhwoDwfv41TNMLRzFP5A"): PlatformMEVX, solana.MustPublicKeyFromBase58("3kxSQybWEeQZsMuNWMRJH4TxrhwoDwfv41TNMLRzFP5A"): PlatformMEVX,

View File

@@ -61,16 +61,13 @@ func main() {
if tx.Program != parser.SolProgramPumpAMM { if tx.Program != parser.SolProgramPumpAMM {
continue continue
} }
if tx.EntryContract == "" || tx.EntryContract == parser.SolProgramPumpAMM || tx.EntryContract == parser.EntryContractOKXDexRouterV2 || tx.EntryContract == "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" {
continue
}
//if tx.Token1Amount.GreaterThanOrEqual(decimal.NewFromFloat(0.1)) || tx.Event != "buy" { //if tx.Token1Amount.GreaterThanOrEqual(decimal.NewFromFloat(0.1)) || tx.Event != "buy" {
// continue // continue
//} //}
// printed = true // printed = true
fmt.Printf("t: %s, block: %d, hash: %s, maker: %s, program: %s, event: %s, token0: %s, entryContract: %s, token balance: %s, EntryContract: %s\n", fmt.Printf("t: %s, block: %d, is cash:%v hash: %s, maker: %s, program: %s, event: %s, token0: %s, entryContract: %s, token balance: %s, EntryContract: %s\n",
time.Now().Format(time.RFC3339Nano), time.Now().Format(time.RFC3339Nano),
tx.Block, tx.GetTxHash(), tx.Maker, tx.Program, tx.Event, tx.Token0Amount, tx.EntryContract, tx.AfterSignerToken0Balance, tx.EntryContract) tx.Block, tx.Cashback, tx.GetTxHash(), tx.Maker, tx.Program, tx.Event, tx.Token0Amount, tx.EntryContract, tx.AfterSignerToken0Balance, tx.EntryContract)
//break //break
} }
//if !printed { //if !printed {

View File

@@ -50,7 +50,8 @@ type Tx struct {
AfterSOLBalance decimal.Decimal `gorm:"column:after_sol_balance;type:numeric" json:"after_sol_balance"` 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"` EntryContract string `gorm:"column:tx_entry_contract;type:entry_contract;default:'none'" json:"tx_entry_contract"`
Mayhem bool Mayhem bool
Cashback bool `json:"is_cashback_coin"`
} }
func (tx *Tx) GetTxHash() string { func (tx *Tx) GetTxHash() string {
@@ -121,6 +122,7 @@ func FromTx(tx *parser.Tx) []*Tx {
EntryContract: s.CheckEntryContract(), EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem, Mayhem: s.Mayhem,
Cashback: s.Cashback,
} }
} else if s.Program == "PumpAMM" { } else if s.Program == "PumpAMM" {
if s.BaseMint.Equals(solana.WrappedSol) { if s.BaseMint.Equals(solana.WrappedSol) {
@@ -175,6 +177,7 @@ func FromTx(tx *parser.Tx) []*Tx {
EntryContract: s.CheckEntryContract(), EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem, Mayhem: s.Mayhem,
Cashback: s.Cashback,
} }
} else { } else {
newTx = &Tx{ newTx = &Tx{
@@ -219,6 +222,7 @@ func FromTx(tx *parser.Tx) []*Tx {
EntryContract: s.CheckEntryContract(), EntryContract: s.CheckEntryContract(),
Mayhem: s.Mayhem, Mayhem: s.Mayhem,
Cashback: s.Cashback,
} }
} }
} }

View File

@@ -62,9 +62,7 @@ func NewClientWithPumpSwap(endpoint string, ch chan SubscriptionMessage) *Client
"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", //Pump AMM "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", //Pump AMM
"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", //Pump "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", //Pump
} }
subscription.Transactions["transactions_sub"].AccountRequired = []string{
"ARu4n5mFdZogZAravu7CcizaojWnS6oqka37gdLT5SZn",
}
subscription.BlocksMeta = make(map[string]*pb.SubscribeRequestFilterBlocksMeta) subscription.BlocksMeta = make(map[string]*pb.SubscribeRequestFilterBlocksMeta)
subscription.BlocksMeta["block_meta"] = &pb.SubscribeRequestFilterBlocksMeta{} subscription.BlocksMeta["block_meta"] = &pb.SubscribeRequestFilterBlocksMeta{}

View File

@@ -177,8 +177,13 @@ func (tx *Tx) Parser() error {
tx.Swaps = append(tx.Swaps, swap) tx.Swaps = append(tx.Swaps, swap)
} }
// tx.Swaps = append(tx.Swaps, swaps...) // tx.Swaps = append(tx.Swaps, swaps...)
j = int(offset[1]) if ii == int(offset[0]) && j == int(offset[1]) {
ii = int(offset[0]) j = j + 1
} else {
j = int(offset[1])
ii = int(offset[0])
}
} else if p, exists := actionPrograms[innerProgramAccount]; exists { } else if p, exists := actionPrograms[innerProgramAccount]; exists {
offset, err := p(tx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)}) offset, err := p(tx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)})
if err != nil { if err != nil {

View File

@@ -79,6 +79,7 @@ type PumpCreateEvent struct {
TokenTotalSupply uint64 TokenTotalSupply uint64
TokenProgram solana.PublicKey TokenProgram solana.PublicKey
IsMayhemMode bool IsMayhemMode bool
IsCashbackEnabled bool
} }
func CreateParser(tx *Tx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { func CreateParser(tx *Tx, instr Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
@@ -148,6 +149,7 @@ func CreateParser(tx *Tx, instr Instruction, innerInstructions InnerInstructions
BaseReserve: decimal.NewFromUint64(createEvent.RealTokenReserves), BaseReserve: decimal.NewFromUint64(createEvent.RealTokenReserves),
QuoteReserve: decimal.Zero, QuoteReserve: decimal.Zero,
Mayhem: createEvent.IsMayhemMode, Mayhem: createEvent.IsMayhemMode,
Cashback: createEvent.IsCashbackEnabled,
UserBaseBalance: userBase, UserBaseBalance: userBase,
UserQuoteBalance: decimal.NewFromUint64(userQuote), UserQuoteBalance: decimal.NewFromUint64(userQuote),
EntryContract: entryContract, EntryContract: entryContract,

View File

@@ -41,6 +41,8 @@ type ammBuyEvent struct {
LastUpdateTimestamp int64 LastUpdateTimestamp int64
MinBaseAmountOut uint64 MinBaseAmountOut uint64
IxName string IxName string
CashbackFeeBasisPoints uint64
Cashback uint64
} }
type ammCreatePoolEvent struct { type ammCreatePoolEvent struct {
@@ -113,6 +115,8 @@ type ammSellEvent struct {
CoinCreator solana.PublicKey CoinCreator solana.PublicKey
CoinCreatorFeeBasisPoints uint64 CoinCreatorFeeBasisPoints uint64
CoinCreatorFee uint64 CoinCreatorFee uint64
CashbackFeeBasisPoints uint64
Cashback uint64
} }
type ammWithdrawEvent struct { type ammWithdrawEvent struct {
@@ -329,6 +333,7 @@ func ammBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstru
userBalance, _ := GetSolAfterTx(result, userIndex) userBalance, _ := GetSolAfterTx(result, userIndex)
userQuote = userQuote.Add(decimal.NewFromUint64(userBalance)) userQuote = userQuote.Add(decimal.NewFromUint64(userBalance))
} }
isCashbackCoin := event.CashbackFeeBasisPoints > 0 || event.Cashback > 0
return []Swap{ return []Swap{
{ {
Program: SolProgramPumpAMM, Program: SolProgramPumpAMM,
@@ -347,6 +352,7 @@ func ammBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstru
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserve - event.BaseAmountOut), BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserve - event.BaseAmountOut),
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserve + event.QuoteAmountIn), QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserve + event.QuoteAmountIn),
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]), Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
Cashback: isCashbackCoin,
UserBaseBalance: userBase, UserBaseBalance: userBase,
UserQuoteBalance: userQuote, UserQuoteBalance: userQuote,
EntryContract: entryContract, EntryContract: entryContract,
@@ -448,6 +454,7 @@ func ammSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr
userBalance, _ := GetSolAfterTx(result, userIndex) userBalance, _ := GetSolAfterTx(result, userIndex)
userQuote = userQuote.Add(decimal.NewFromUint64(userBalance)) userQuote = userQuote.Add(decimal.NewFromUint64(userBalance))
} }
isCashbackCoin := event.CashbackFeeBasisPoints > 0 || event.Cashback > 0
return []Swap{ return []Swap{
{ {
Program: SolProgramPumpAMM, Program: SolProgramPumpAMM,
@@ -466,6 +473,7 @@ func ammSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn), BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn),
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut), QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut),
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]), Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
Cashback: isCashbackCoin,
UserBaseBalance: userBase, UserBaseBalance: userBase,
UserQuoteBalance: userQuote, UserQuoteBalance: userQuote,
EntryContract: entryContract, EntryContract: entryContract,

View File

@@ -326,7 +326,9 @@ func FromRpcTransactionWithMeta(tx rpc.TransactionWithMeta, blockTime *uint64, s
} }
sTx.Meta.Fee = meta.Fee sTx.Meta.Fee = meta.Fee
//sTx.Meta.InnerInstructions = meta.InnerInstructions //sTx.Meta.InnerInstructions = meta.InnerInstructions
if meta.ComputeUnitsConsumed != nil {
sTx.Meta.ComputeUnitsConsumed = *meta.ComputeUnitsConsumed
}
for _, innerInstr := range meta.InnerInstructions { for _, innerInstr := range meta.InnerInstructions {
var instrs []Instruction var instrs []Instruction
for _, instr := range innerInstr.Instructions { for _, instr := range innerInstr.Instructions {
@@ -514,6 +516,7 @@ func intSliceFromUint16Slice(in []uint16) []int {
} }
return out return out
} }
func getAtaIdxByOwner(result *RawTx, owner solana.PublicKey, mint solana.PublicKey) (int, error) { func getAtaIdxByOwner(result *RawTx, owner solana.PublicKey, mint solana.PublicKey) (int, error) {
var preBalance *TokenBalance var preBalance *TokenBalance
for _, pre := range result.Meta.PreTokenBalances { for _, pre := range result.Meta.PreTokenBalances {

1
tx.go
View File

@@ -31,6 +31,7 @@ type Swap struct {
BaseReserve decimal.Decimal BaseReserve decimal.Decimal
QuoteReserve decimal.Decimal QuoteReserve decimal.Decimal
Mayhem bool Mayhem bool
Cashback bool
UserBaseBalance decimal.Decimal UserBaseBalance decimal.Decimal
UserQuoteBalance decimal.Decimal UserQuoteBalance decimal.Decimal