Add JupiterAggregatorV6 pumpfun parse

This commit is contained in:
bijianing97
2026-01-22 17:10:13 +08:00
parent 36db4729d4
commit 45107aa8c3
3 changed files with 278 additions and 13 deletions

View File

@@ -858,6 +858,101 @@ func pumpSwapSellAtIdx0V2(amount uint64, plan []RoutePlanStepV2) (uint64, int) {
return ret, i
}
type pumpWrappedMatch struct {
IsBuy bool
InAmount uint64
OutAmount uint64
}
func isPumpWrappedBuy(kind SwapKind) bool {
switch kind {
case PumpWrappedBuy, PumpWrappedBuyV2, PumpWrappedBuyV3, PumpWrappedBuyV4:
return true
default:
return false
}
}
func isPumpWrappedSell(kind SwapKind) bool {
switch kind {
case PumpWrappedSell, PumpWrappedSellV2, PumpWrappedSellV3, PumpWrappedSellV4:
return true
default:
return false
}
}
func pumpWrappedAtIdx0(in uint64, out uint64, plan []RoutePlanStep) (pumpWrappedMatch, int) {
var (
ret pumpWrappedMatch
count int
)
for _, step := range plan {
if step.InputIdx != 0 {
continue
}
if !isPumpWrappedBuy(step.Swap.Kind) && !isPumpWrappedSell(step.Swap.Kind) {
continue
}
count++
if count > 1 {
return pumpWrappedMatch{}, count
}
ret.IsBuy = isPumpWrappedBuy(step.Swap.Kind)
ret.InAmount = in * uint64(step.Percent) / 100
if step.Percent == 100 {
ret.OutAmount = out
}
}
return ret, count
}
func pumpWrappedAtIdx0V2(in uint64, out uint64, plan []RoutePlanStepV2) (pumpWrappedMatch, int) {
var (
ret pumpWrappedMatch
count int
)
for _, step := range plan {
if step.InputIdx != 0 {
continue
}
if !isPumpWrappedBuy(step.Swap.Kind) && !isPumpWrappedSell(step.Swap.Kind) {
continue
}
count++
if count > 1 {
return pumpWrappedMatch{}, count
}
ret.IsBuy = isPumpWrappedBuy(step.Swap.Kind)
ret.InAmount = in * uint64(step.Bps) / 10000
if step.Bps == 10000 {
ret.OutAmount = out
}
}
return ret, count
}
func findPumpFunMint(staticKeys []solana.PublicKey, accounts []uint8) (solana.PublicKey, bool, error) {
for i, acctIdx := range accounts {
key, err := getStaticKey(staticKeys, int(acctIdx))
if err != nil {
return solana.PublicKey{}, false, err
}
if !key.Equals(pumpProgramID) {
continue
}
if i+3 >= len(accounts) {
return solana.PublicKey{}, false, nil
}
mint, err := getStaticKey(staticKeys, int(accounts[i+3]))
if err != nil {
return solana.PublicKey{}, false, err
}
return mint, true, nil
}
return solana.PublicKey{}, false, nil
}
// only decodes inputIdx = 0 container pumpSwap instructions for now
func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (*TxSignal, error) {
msg := tx.Message
@@ -879,6 +974,9 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
sourceMint solana.PublicKey
inputAmount uint64
planCount int
wrapped pumpWrappedMatch
wrappedCnt int
exactOut bool
err error
)
@@ -891,12 +989,28 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
return nil, err
}
inputAmount, planCount = pumpSwapSellAtIdx0V2(args.In, args.Plan)
wrapped, wrappedCnt = pumpWrappedAtIdx0V2(args.In, args.Out, args.Plan)
case bytes.Equal(disc, jupiterSharedAccountsRouteV2):
args, err := decodeJupiterV6SharedAccountsRouteV2Arg(instruction.Data[8:])
if err != nil {
return nil, err
}
inputAmount, planCount = pumpSwapSellAtIdx0V2(args.In, args.RoutePlan)
wrapped, wrappedCnt = pumpWrappedAtIdx0V2(args.In, args.QuotedOut, args.RoutePlan)
case bytes.Equal(disc, jupiterExactOutRouteV2):
args, err := decodeJupiterV6ExactOutRouteV2Arg(instruction.Data[8:])
if err != nil {
return nil, err
}
exactOut = true
wrapped, wrappedCnt = pumpWrappedAtIdx0V2(args.QuotedIn, args.Out, args.RoutePlan)
case bytes.Equal(disc, jupiterSharedAccountsExactOutRouteV2):
args, err := decodeJupiterV6SharedAccountsExactOutRouteV2Arg(instruction.Data[8:])
if err != nil {
return nil, err
}
exactOut = true
wrapped, wrappedCnt = pumpWrappedAtIdx0V2(args.QuotedIn, args.Out, args.RoutePlan)
case bytes.Equal(disc, jupiterRoute):
args, err := decodeJupiterV6RouteArg(instruction.Data[8:])
if err != nil {
@@ -904,6 +1018,14 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
}
_ = args
inputAmount, planCount = pumpSwapSellAtIdx0(args.In, args.Plan)
wrapped, wrappedCnt = pumpWrappedAtIdx0(args.In, args.QuotedOut, args.Plan)
case bytes.Equal(disc, jupiterSharedAccountsExactOutRoute):
args, err := decodeJupiterV6SharedAccountsExactOutRouteArg(instruction.Data[8:])
if err != nil {
return nil, err
}
exactOut = true
wrapped, wrappedCnt = pumpWrappedAtIdx0(args.QuotedIn, args.Out, args.Plan)
case bytes.Equal(disc, jupiterSharedAccountsRoute):
args, err := decodeJupiterV6SharedAccountsRouteArg(instruction.Data[8:])
if err != nil {
@@ -911,9 +1033,62 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
}
_ = args
inputAmount, planCount = pumpSwapSellAtIdx0(args.In, args.Plan)
wrapped, wrappedCnt = pumpWrappedAtIdx0(args.In, args.QuotedOut, args.Plan)
default:
return nil, nil
}
if wrappedCnt > 1 {
logger.Warn("pumpWrapped at inputIdx=0: multiple instances found", "tx", tx.Signatures[0].String(), "planCount", wrappedCnt)
}
if wrapped.InAmount > 0 {
mint, ok, err := findPumpFunMint(tx.Message.StaticAccountKeys, instruction.Accounts)
if err != nil {
return nil, err
}
if !ok {
return nil, nil
}
event := "sell"
exactSol := false
var (
token0AmountUint64 uint64
token1AmountUint64 uint64
)
if wrapped.IsBuy {
event = "buy"
exactSol = !exactOut
token0AmountUint64 = wrapped.OutAmount
token1AmountUint64 = wrapped.InAmount
} else {
exactSol = exactOut && wrapped.OutAmount > 0
token0AmountUint64 = wrapped.InAmount
token1AmountUint64 = wrapped.OutAmount
}
token0Amount := decimal.Zero
if token0AmountUint64 > 0 {
token0Amount = formatTokenAmount(token0AmountUint64)
}
token1Amount := decimal.Zero
if token1AmountUint64 > 0 {
token1Amount = formatSolAmount(token1AmountUint64)
}
return &TxSignal{
TxHash: tx.Signatures[0].String(),
Maker: tx.Message.StaticAccountKeys[0].String(),
Token0Address: mint.String(),
Token1Address: wsolMint,
Token0Amount: token0Amount,
Token1Amount: token1Amount,
Program: "Pump",
Event: event,
IsToken2022: false,
IsMayhemMode: false,
ExactSOL: exactSol,
Block: tx.Block,
Token0AmountUint64: token0AmountUint64,
Token1AmountUint64: token1AmountUint64,
}, nil
}
if planCount > 1 {
// multiple pumpSwapSell at inputIdx=0? should not happen
logger.Warn("pumpSwapSell at inputIdx=0: multiple instances found", "tx", tx.Signatures[0].String(), "planCount", planCount)