chore: add gmgn and remove entry contract
This commit is contained in:
@@ -45,7 +45,6 @@ type TxSignal struct {
|
|||||||
IsToken2022 bool `json:"is_token2022"`
|
IsToken2022 bool `json:"is_token2022"`
|
||||||
IsMayhemMode bool `json:"is_mayhem_mode"`
|
IsMayhemMode bool `json:"is_mayhem_mode"`
|
||||||
TxFee decimal.Decimal `json:"tx_fee"`
|
TxFee decimal.Decimal `json:"tx_fee"`
|
||||||
EntryContract string `json:"entry_contract"`
|
|
||||||
|
|
||||||
ExactSOL bool `json:"exact_in"`
|
ExactSOL bool `json:"exact_in"`
|
||||||
|
|
||||||
|
|||||||
@@ -23,42 +23,30 @@ const (
|
|||||||
// program ids
|
// program ids
|
||||||
var (
|
var (
|
||||||
pumpProgramID = solana.MustPublicKeyFromBase58("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
|
pumpProgramID = solana.MustPublicKeyFromBase58("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
|
||||||
pumpProgramIDString = pumpProgramID.String()
|
|
||||||
// has no sell function with pump and pump.amm program
|
// has no sell function with pump and pump.amm program
|
||||||
azczProgramID = solana.MustPublicKeyFromBase58("AzcZqCRUQgKEg5FTAgY7JacATABEYCEfMbjXEzspLYFB")
|
azczProgramID = solana.MustPublicKeyFromBase58("AzcZqCRUQgKEg5FTAgY7JacATABEYCEfMbjXEzspLYFB")
|
||||||
azczProgramIDString = azczProgramID.String()
|
|
||||||
|
|
||||||
// only buy function with pump program
|
// only buy function with pump program
|
||||||
f5tfProgramID = solana.MustPublicKeyFromBase58("F5tfvbLog9VdGUPqBDTT8rgXvTTcq7e5UiGnupL1zvBq")
|
f5tfProgramID = solana.MustPublicKeyFromBase58("F5tfvbLog9VdGUPqBDTT8rgXvTTcq7e5UiGnupL1zvBq")
|
||||||
f5tfProgramIDString = f5tfProgramID.String()
|
|
||||||
// only pump.fun function
|
// only pump.fun function
|
||||||
photonProgramID = solana.MustPublicKeyFromBase58("BSfD6SHZigAfDWSjzD5Q41jw8LmKwtmjskPH9XW1mrRW")
|
photonProgramID = solana.MustPublicKeyFromBase58("BSfD6SHZigAfDWSjzD5Q41jw8LmKwtmjskPH9XW1mrRW")
|
||||||
photonProgramIDString = photonProgramID.String()
|
|
||||||
|
|
||||||
pumpAmmProgramID = solana.MustPublicKeyFromBase58("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA")
|
pumpAmmProgramID = solana.MustPublicKeyFromBase58("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA")
|
||||||
pumpAmmProgramIDString = pumpAmmProgramID.String()
|
|
||||||
|
|
||||||
boboProgramID = solana.MustPublicKeyFromBase58("BobogA5N2KN2GG4XN3E3rNNRw3L8H1QPXp7QLxGrNHGM")
|
boboProgramID = solana.MustPublicKeyFromBase58("BobogA5N2KN2GG4XN3E3rNNRw3L8H1QPXp7QLxGrNHGM")
|
||||||
boboProgramIDString = boboProgramID.String()
|
|
||||||
|
|
||||||
qtkvProgramID = solana.MustPublicKeyFromBase58("qtkvapJEvRWWrB7i5K6RaA1kvq5x3qmMKZ98ad71XQ7")
|
qtkvProgramID = solana.MustPublicKeyFromBase58("qtkvapJEvRWWrB7i5K6RaA1kvq5x3qmMKZ98ad71XQ7")
|
||||||
qtkvProgramIDString = qtkvProgramID.String()
|
|
||||||
|
|
||||||
// only buy function with pump program
|
// only buy function with pump program
|
||||||
fjszProgramID = solana.MustPublicKeyFromBase58("FJsZbftBqRLfF7uqUKpm4s2goDr6xsQ5Q3mN7AFJB6hK")
|
fjszProgramID = solana.MustPublicKeyFromBase58("FJsZbftBqRLfF7uqUKpm4s2goDr6xsQ5Q3mN7AFJB6hK")
|
||||||
fjszProgramIDString = fjszProgramID.String()
|
|
||||||
|
|
||||||
flasProgramID = solana.MustPublicKeyFromBase58("FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9")
|
flasProgramID = solana.MustPublicKeyFromBase58("FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9")
|
||||||
flasProgramIDString = flasProgramID.String()
|
|
||||||
|
|
||||||
terminalProgramID = solana.MustPublicKeyFromBase58("term9YPb9mzAsABaqN71A4xdbxHmpBNZavpBiQKZzN3")
|
terminalProgramID = solana.MustPublicKeyFromBase58("term9YPb9mzAsABaqN71A4xdbxHmpBNZavpBiQKZzN3")
|
||||||
terminalProgramIDString = terminalProgramID.String()
|
|
||||||
|
|
||||||
jupiterV6ProgramID = solana.MustPublicKeyFromBase58("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4")
|
jupiterV6ProgramID = solana.MustPublicKeyFromBase58("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4")
|
||||||
jupiterV6ProgramIDString = jupiterV6ProgramID.String()
|
|
||||||
|
|
||||||
gmgnProgramID = solana.MustPublicKeyFromBase58("GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb")
|
gmgnProgramID = solana.MustPublicKeyFromBase58("GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb")
|
||||||
gmgnProgramIDString = gmgnProgramID.String()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountNotFoundError struct {
|
type AccountNotFoundError struct {
|
||||||
@@ -108,6 +96,8 @@ var (
|
|||||||
terminalBuyTokensIX = []byte{0xa6, 0x54, 0x14, 0x96, 0x9f, 0x77, 0x59, 0xca}
|
terminalBuyTokensIX = []byte{0xa6, 0x54, 0x14, 0x96, 0x9f, 0x77, 0x59, 0xca}
|
||||||
terminalSellTokensIX = []byte{0xbe, 0x84, 0xa2, 0x96, 0x93, 0x7c, 0xf8, 0x6b}
|
terminalSellTokensIX = []byte{0xbe, 0x84, 0xa2, 0x96, 0x93, 0x7c, 0xf8, 0x6b}
|
||||||
terminalAmmSellTokensIX = []byte{0x40, 0x64, 0x97, 0xb9, 0x16, 0xfa, 0xec, 0xb1}
|
terminalAmmSellTokensIX = []byte{0x40, 0x64, 0x97, 0xb9, 0x16, 0xfa, 0xec, 0xb1}
|
||||||
|
|
||||||
|
gmgnBuyTokensIX = []byte{0x66, 0x06, 0x3d, 0x12, 0x01, 0xda, 0xeb, 0xea}
|
||||||
)
|
)
|
||||||
|
|
||||||
type compiledInstruction struct {
|
type compiledInstruction struct {
|
||||||
@@ -312,50 +302,53 @@ func ParseTransaction(update *SubscribeUpdateTransaction, loader *AddressTables,
|
|||||||
switch programID {
|
switch programID {
|
||||||
case pumpProgramID:
|
case pumpProgramID:
|
||||||
txRes, err := parsePumpInstruction(versioned, i)
|
txRes, err := parsePumpInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "pump", pumpProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "pump")
|
||||||
case azczProgramID:
|
case azczProgramID:
|
||||||
txRes, err := parseAzczInstruction(versioned, i)
|
txRes, err := parseAzczInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "azcz", azczProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "azcz")
|
||||||
case f5tfProgramID:
|
case f5tfProgramID:
|
||||||
txRes, err := parseF5tfInstruction(versioned, i)
|
txRes, err := parseF5tfInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "f5tf", f5tfProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "f5tf")
|
||||||
case flasProgramID:
|
case flasProgramID:
|
||||||
txRes, err := parseFlasInstruction(versioned, i)
|
txRes, err := parseFlasInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "flas", flasProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "flas")
|
||||||
case photonProgramID:
|
case photonProgramID:
|
||||||
txRes, err := parsePhotonInstruction(versioned, i)
|
txRes, err := parsePhotonInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "photon", photonProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "photon")
|
||||||
case pumpAmmProgramID:
|
case pumpAmmProgramID:
|
||||||
txRes, err := parsePumpAmmInstruction(versioned, i)
|
txRes, err := parsePumpAmmInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "pumpamm", pumpAmmProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "pumpamm")
|
||||||
case boboProgramID:
|
case boboProgramID:
|
||||||
txRes, err := parseBoboInstruction(versioned, i)
|
txRes, err := parseBoboInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "bobo", boboProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "bobo")
|
||||||
case qtkvProgramID:
|
case qtkvProgramID:
|
||||||
txRes, err := parseQtkvInstruction(versioned, i)
|
txRes, err := parseQtkvInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "qtkv", qtkvProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "qtkv")
|
||||||
case fjszProgramID:
|
case fjszProgramID:
|
||||||
txRes, err := parseFjszInstruction(versioned, i)
|
txRes, err := parseFjszInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "fjsz", fjszProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "fjsz")
|
||||||
case terminalProgramID:
|
case terminalProgramID:
|
||||||
txRes, err := parseTermInstruction(versioned, i)
|
txRes, err := parseTermInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "terminal", terminalProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "terminal")
|
||||||
case jupiterV6ProgramID:
|
case jupiterV6ProgramID:
|
||||||
txRes, err := parseJupiterV6Instruction(versioned, i)
|
txRes, err := parseJupiterV6Instruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "jupiterv6", jupiterV6ProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "jupiterv6")
|
||||||
case okxDexRouteV2ProgramID:
|
case okxDexRouteV2ProgramID:
|
||||||
txRes, err := parseOkxDexRouteV2Instruction(versioned, i)
|
txRes, err := parseOkxDexRouteV2Instruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "okxdexroutev2", okxDexRouteV2ProgramIDString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "okxdexroutev2")
|
||||||
case dflowProgramID:
|
case dflowProgramID:
|
||||||
txRes, err := parseDFlowInstruction(versioned, i)
|
txRes, err := parseDFlowInstruction(versioned, i)
|
||||||
parsed = appendParsed(now, parsed, txRes, err, txHash, "dflow", dflowProgramString)
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "dflow")
|
||||||
|
case gmgnProgramID:
|
||||||
|
txRes, err := parseGMGNInstruction(versioned, i)
|
||||||
|
parsed = appendParsed(now, parsed, txRes, err, txHash, "gmgn")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendParsed(start time.Time, list []*TxSignal, parsed *TxSignal, err error, txHash [64]byte, label string, entryContract string) []*TxSignal {
|
func appendParsed(start time.Time, list []*TxSignal, parsed *TxSignal, err error, txHash [64]byte, label string) []*TxSignal {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !strings.HasPrefix(err.Error(), "account index") {
|
if !strings.HasPrefix(err.Error(), "account index") {
|
||||||
logger.Debug("txparser: failed to parse", "label", label, "instruction", err, "tx_hash", base58.Encode(txHash[:]))
|
logger.Debug("txparser: failed to parse", "label", label, "instruction", err, "tx_hash", base58.Encode(txHash[:]))
|
||||||
@@ -363,7 +356,6 @@ func appendParsed(start time.Time, list []*TxSignal, parsed *TxSignal, err error
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
if parsed != nil {
|
if parsed != nil {
|
||||||
parsed.EntryContract = entryContract
|
|
||||||
parsed.Label = label
|
parsed.Label = label
|
||||||
if !start.IsZero() {
|
if !start.IsZero() {
|
||||||
parsed.ParseEnd = time.Now()
|
parsed.ParseEnd = time.Now()
|
||||||
@@ -1007,6 +999,66 @@ func parseFlasBuy(tx *versionedTransaction, instructionIndex int) (*TxSignal, er
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseGMGNInstruction(tx *versionedTransaction, instructionIndex int) (*TxSignal, error) {
|
||||||
|
msg := tx.Message
|
||||||
|
if instructionIndex >= len(msg.Instructions) {
|
||||||
|
return nil, fmt.Errorf("instruction index out of bounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction := msg.Instructions[instructionIndex]
|
||||||
|
if len(instruction.Data) == 0 {
|
||||||
|
return nil, fmt.Errorf("data is empty")
|
||||||
|
}
|
||||||
|
if len(instruction.Data) < 8 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if matchMethod(instruction.Data, gmgnBuyTokensIX) {
|
||||||
|
return parseGMGNBuy(tx, &instruction)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGMGNBuy(tx *versionedTransaction, instruction *compiledInstruction) (*TxSignal, error) {
|
||||||
|
if len(instruction.Accounts) < 8 {
|
||||||
|
return nil, fmt.Errorf("accounts too short")
|
||||||
|
}
|
||||||
|
if len(instruction.Data) < 24 {
|
||||||
|
return nil, fmt.Errorf("data too short for gmgn buy args, len=%d", len(instruction.Data))
|
||||||
|
}
|
||||||
|
|
||||||
|
staticKeys := tx.Message.StaticAccountKeys
|
||||||
|
mint, err := getStaticKey(staticKeys, int(instruction.Accounts[2]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user, err := getStaticKey(staticKeys, int(instruction.Accounts[6]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
solAmount := binary.LittleEndian.Uint64(instruction.Data[8:16])
|
||||||
|
tokenAmount := binary.LittleEndian.Uint64(instruction.Data[16:24])
|
||||||
|
|
||||||
|
return &TxSignal{
|
||||||
|
TxHash: tx.Signatures[0].String(),
|
||||||
|
Label: "gmgn",
|
||||||
|
Maker: user.String(),
|
||||||
|
Token0Address: mint.String(),
|
||||||
|
Token1Address: wsolMint,
|
||||||
|
Token0Amount: formatTokenAmount(tokenAmount),
|
||||||
|
Token1Amount: formatSolAmount(solAmount),
|
||||||
|
Program: "Pump",
|
||||||
|
Event: "buy",
|
||||||
|
IsToken2022: false,
|
||||||
|
IsMayhemMode: false,
|
||||||
|
ExactSOL: true,
|
||||||
|
Block: tx.Block,
|
||||||
|
Token0AmountUint64: tokenAmount,
|
||||||
|
Token1AmountUint64: solAmount,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parsePhotonInstruction(tx *versionedTransaction, instructionIndex int) (*TxSignal, error) {
|
func parsePhotonInstruction(tx *versionedTransaction, instructionIndex int) (*TxSignal, error) {
|
||||||
msg := tx.Message
|
msg := tx.Message
|
||||||
if instructionIndex >= len(msg.Instructions) {
|
if instructionIndex >= len(msg.Instructions) {
|
||||||
|
|||||||
Reference in New Issue
Block a user