135 lines
3.3 KiB
Go
135 lines
3.3 KiB
Go
package shreder
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
"github.com/gagliardetto/solana-go"
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
var dbotProgramID = solana.MustPublicKeyFromBase58("DBotWvSso9oD1ZB3aHx2LiD2ZoFpF8PbKjaT4uHKLLVs")
|
|
|
|
var (
|
|
dbotPumpFunBuyIX = []byte{0x4e, 0x13, 0x6d, 0x72, 0x3d, 0x72, 0xbe, 0x9d}
|
|
dbotPumpAmmBuyIX = []byte{0x99, 0x76, 0xb6, 0x1e, 0xe4, 0x03, 0xdc, 0xf4}
|
|
)
|
|
|
|
func parseDbotInstruction(tx VersionedTransaction, instructionIndex int) (TxSignalBatch, error) {
|
|
if instructionIndex >= len(tx.Instructions) {
|
|
return nil, fmt.Errorf("instruction index out of bounds")
|
|
}
|
|
ix := tx.Instructions[instructionIndex]
|
|
if len(ix.Data) < 8 {
|
|
return nil, nil
|
|
}
|
|
|
|
isPumpFun := false
|
|
isPumpAmm := false
|
|
|
|
if len(ix.Accounts) > 11 {
|
|
key, err := tx.GetAccount(int(ix.Accounts[11]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if key.Equals(pumpProgramID) {
|
|
isPumpFun = true
|
|
}
|
|
}
|
|
|
|
if len(ix.Accounts) > 16 {
|
|
key, err := tx.GetAccount(int(ix.Accounts[16]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if key.Equals(pumpAmmProgramID) {
|
|
isPumpAmm = true
|
|
}
|
|
}
|
|
|
|
disc := ix.Data[:8]
|
|
|
|
if isPumpFun {
|
|
if !bytes.Equal(disc, dbotPumpFunBuyIX) {
|
|
return nil, nil
|
|
}
|
|
if len(ix.Data) < 16 {
|
|
return nil, fmt.Errorf("data too short for dbot pumpfun buy args, len=%d", len(ix.Data))
|
|
}
|
|
if len(ix.Accounts) < 3 {
|
|
return nil, fmt.Errorf("accounts too short")
|
|
}
|
|
|
|
mint, err := tx.GetAccount(int(ix.Accounts[2]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
solAmount := binary.LittleEndian.Uint64(ix.Data[8:16])
|
|
|
|
return TxSignalBatch{&TxSignal{
|
|
TxHash: tx.Signatures[0].String(),
|
|
Label: "dbot",
|
|
Maker: tx.StaticAccountKeys[0].String(),
|
|
Token0Address: mint.String(),
|
|
Token1Address: wsolMint,
|
|
Token0Amount: decimal.Zero,
|
|
Token1Amount: formatSolAmount(solAmount),
|
|
Program: "Pump",
|
|
Event: "buy",
|
|
ExactSOL: true,
|
|
IsToken2022: false,
|
|
IsMayhemMode: false,
|
|
Block: tx.Block,
|
|
Token0AmountUint64: 0,
|
|
Token1AmountUint64: solAmount,
|
|
}}, nil
|
|
}
|
|
|
|
if isPumpAmm {
|
|
if !bytes.Equal(disc, dbotPumpAmmBuyIX) {
|
|
return nil, nil
|
|
}
|
|
if len(ix.Data) < 16 {
|
|
return nil, fmt.Errorf("data too short for dbot pumpamm buy args, len=%d", len(ix.Data))
|
|
}
|
|
if len(ix.Accounts) < 5 {
|
|
return nil, fmt.Errorf("accounts too short")
|
|
}
|
|
|
|
base, err := tx.GetAccount(int(ix.Accounts[3]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
quote, err := tx.GetAccount(int(ix.Accounts[4]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !quote.Equals(solana.WrappedSol) {
|
|
return nil, nil
|
|
}
|
|
|
|
solAmount := binary.LittleEndian.Uint64(ix.Data[8:16])
|
|
|
|
return TxSignalBatch{&TxSignal{
|
|
TxHash: tx.Signatures[0].String(),
|
|
Label: "dbot",
|
|
Maker: tx.StaticAccountKeys[0].String(),
|
|
Token0Address: base.String(),
|
|
Token1Address: wsolMint,
|
|
Token0Amount: decimal.Zero,
|
|
Token1Amount: formatSolAmount(solAmount),
|
|
Program: "PumpAMM",
|
|
Event: "buy",
|
|
ExactSOL: true,
|
|
IsToken2022: false,
|
|
IsMayhemMode: false,
|
|
Block: tx.Block,
|
|
Token0AmountUint64: 0,
|
|
Token1AmountUint64: solAmount,
|
|
}}, nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|