pump and pump swap errTx parser
This commit is contained in:
127
pump.go
127
pump.go
@@ -34,10 +34,19 @@ func pumpParser(tx *Tx, instruction Instruction, innerInstructions InnerInstruct
|
||||
|
||||
switch discriminator {
|
||||
case pumpBuyV2Discriminator, pumpBuyDiscriminator, pumpSellDiscriminator:
|
||||
if tx.Err != nil {
|
||||
return failedTxBuyOrSellParser(tx, instruction, innerInstructions, offset)
|
||||
}
|
||||
return BuyOrSellParser(tx, instruction, innerInstructions, offset)
|
||||
case pumpCreateDiscriminator, pumpCreateV2Discriminator:
|
||||
if tx.Err != nil {
|
||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||
}
|
||||
return CreateParser(tx, instruction, innerInstructions, offset)
|
||||
case pumpMigrateDiscriminator:
|
||||
if tx.Err != nil {
|
||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||
}
|
||||
return MigrateParser(tx, instruction, innerInstructions, offset)
|
||||
default:
|
||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||
@@ -178,6 +187,16 @@ type PumpTradeEvent struct {
|
||||
|
||||
CreatorFeeBasisPoints uint64
|
||||
CreatorFee uint64
|
||||
|
||||
TrackVolume bool
|
||||
TotalUnclaimedTokens uint64
|
||||
TotalClaimedTokens uint64
|
||||
CurrentSolVolume uint64
|
||||
LastUpdateTimestamp int64
|
||||
IxName string
|
||||
MayhemMode bool
|
||||
CashbackFeeBasisPoints uint64
|
||||
Cashback uint64
|
||||
}
|
||||
|
||||
type PumpTradeFeeArg struct {
|
||||
@@ -193,6 +212,112 @@ type CompleteEvent struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type PumpTradeArgs struct {
|
||||
Discriminator [8]byte
|
||||
Amount1 uint64
|
||||
Amount2 uint64
|
||||
}
|
||||
|
||||
func failedTxBuyOrSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||
if tx.Err == nil || tx.Err.UnKnown != "" {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("tx pump failed but error is nil, offset, %d, %d", offset[0], offset[1])
|
||||
}
|
||||
if tx.Err.Variant != InstructionError {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("failed tx pump failed but error variant is not instruction error, offset, %d, %d", offset[0], offset[1])
|
||||
}
|
||||
if tx.Err.Enum != Custom && tx.Err.Enum != ComputationalBudgetExceeded {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("failed tx pump failed but error is not custom or computational budget exceeded, offset, %d, %d", offset[0], offset[1])
|
||||
}
|
||||
if tx.Err.Enum == Custom {
|
||||
if !(tx.Err.CustomCode == 1 ||
|
||||
tx.Err.CustomCode == 6042 ||
|
||||
tx.Err.CustomCode == 6041 ||
|
||||
tx.Err.CustomCode == 6040 ||
|
||||
tx.Err.CustomCode == 6023 || tx.Err.CustomCode == 6021 || tx.Err.CustomCode == 6003 || tx.Err.CustomCode == 6002) {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("failed tx pump failed but custom error code is unexpected, offset, %d, %d, code: %d", offset[0], offset[1], tx.Err.CustomCode)
|
||||
}
|
||||
}
|
||||
|
||||
result := tx.rawTx
|
||||
var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
|
||||
|
||||
user := result.accountList[instruction.Accounts[6]]
|
||||
ataUserIdx := instruction.Accounts[5]
|
||||
userIndex := instruction.Accounts[6]
|
||||
mint := result.accountList[instruction.Accounts[2]]
|
||||
var args PumpTradeArgs
|
||||
err := agbinary.NewBorshDecoder(instruction.Data[:]).Decode(&args)
|
||||
if err != nil {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("failed tx pump buy/sell decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||
}
|
||||
var event string
|
||||
var (
|
||||
solAmount, tokenAmount uint64
|
||||
)
|
||||
if bytes.Equal(args.Discriminator[:], pumpBuyV2Discriminator[:]) {
|
||||
event = "buy_failed"
|
||||
solAmount = args.Amount1
|
||||
tokenAmount = args.Amount2
|
||||
} else if bytes.Equal(args.Discriminator[:], pumpBuyDiscriminator[:]) {
|
||||
event = "buy_failed"
|
||||
solAmount = args.Amount2
|
||||
tokenAmount = args.Amount1
|
||||
} else if bytes.Equal(args.Discriminator[:], pumpSellDiscriminator[:]) {
|
||||
event = "sell_failed"
|
||||
solAmount = args.Amount2
|
||||
tokenAmount = args.Amount1
|
||||
} else {
|
||||
return nil, increaseOffset(offset), fmt.Errorf("unknown pump trade instruction discriminator, offset, %d, %d", offset[0], offset[1])
|
||||
}
|
||||
var baseTokenProgram solana.PublicKey
|
||||
|
||||
if event == "buy_failed" {
|
||||
baseTokenProgram = result.accountList[instruction.Accounts[8]]
|
||||
} else {
|
||||
baseTokenProgram = result.accountList[instruction.Accounts[9]]
|
||||
}
|
||||
if !user.IsOnCurve() && (entryContract.Equals(okxDexRoutersV2) || entryContract.Equals(okxAggregatorV2)) {
|
||||
userBaseAmount, ataIndex := tokenBalanceChange(result, 0, baseTokenProgram, mint)
|
||||
//&& userBaseAmount.BigInt().Uint64() == tradeEvent.TokenAmount
|
||||
if !userBaseAmount.IsZero() {
|
||||
user = result.accountList[0]
|
||||
userIndex = 0
|
||||
ataUserIdx = ataIndex
|
||||
}
|
||||
}
|
||||
|
||||
userBase := getAccountBalanceAfterTx(result, ataUserIdx)
|
||||
userQuote, _ := GetSolAfterTx(result, userIndex)
|
||||
|
||||
bcIdx := instruction.Accounts[3]
|
||||
bcAtaIndex := instruction.Accounts[4]
|
||||
solReserves, _ := GetSolAfterTx(result, bcIdx)
|
||||
tokenReserves := getAccountBalanceAfterTx(result, bcAtaIndex)
|
||||
swaps := []Swap{
|
||||
{
|
||||
Program: SolProgramPump,
|
||||
Event: event,
|
||||
Pool: result.accountList[instruction.Accounts[3]],
|
||||
BaseMint: mint,
|
||||
QuoteMint: solana.PublicKey{},
|
||||
BaseTokenProgram: baseTokenProgram,
|
||||
QuoteTokenProgram: solana.PublicKey{},
|
||||
BaseMintDecimals: 6,
|
||||
QuoteMintDecimals: 9,
|
||||
User: user,
|
||||
BaseAmount: decimal.NewFromUint64(tokenAmount),
|
||||
QuoteAmount: decimal.NewFromUint64(solAmount),
|
||||
BaseReserve: tokenReserves,
|
||||
QuoteReserve: decimal.NewFromUint64(solReserves),
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[1]]),
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: decimal.NewFromUint64(userQuote),
|
||||
EntryContract: entryContract,
|
||||
},
|
||||
}
|
||||
return swaps, offset, nil
|
||||
}
|
||||
|
||||
func BuyOrSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||
result := tx.rawTx
|
||||
var entryContract = result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
|
||||
@@ -314,6 +439,7 @@ func BuyOrSellParser(tx *Tx, instruction Instruction, innerInstructions InnerIns
|
||||
solAmount = solAmount - fee
|
||||
}
|
||||
}
|
||||
isCashbackCoin := tradeEvent.CashbackFeeBasisPoints > 0 || tradeEvent.Cashback > 0
|
||||
swaps := []Swap{
|
||||
{
|
||||
Program: SolProgramPump,
|
||||
@@ -335,6 +461,7 @@ func BuyOrSellParser(tx *Tx, instruction Instruction, innerInstructions InnerIns
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: decimal.NewFromUint64(userQuote),
|
||||
EntryContract: entryContract,
|
||||
Cashback: isCashbackCoin,
|
||||
},
|
||||
}
|
||||
if completed {
|
||||
|
||||
Reference in New Issue
Block a user