pipo tx parse

This commit is contained in:
thloyi
2026-01-23 17:58:59 +08:00
parent 6bab10866b
commit 9f73e8f57f
12 changed files with 1172 additions and 746 deletions

View File

@@ -859,21 +859,16 @@ func pumpSwapSellAtIdx0V2(amount uint64, plan []RoutePlanStepV2) (uint64, int) {
}
// only decodes inputIdx = 0 container pumpSwap instructions for now
func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (*TxSignal, error) {
msg := tx.Message
if instructionIndex >= len(msg.Instructions) {
return nil, fmt.Errorf("instruction index out of bounds")
}
func parseJupiterV6Instruction(tx TransactionGetter, accounts []uint8, data []byte) (*TxSignal, error) {
instruction := msg.Instructions[instructionIndex]
if len(instruction.Data) == 0 {
if len(data) == 0 {
return nil, fmt.Errorf("data is empty")
}
if len(instruction.Data) < 8 {
if len(data) < 8 {
return nil, nil
}
disc := instruction.Data[:8]
disc := data[:8]
var (
sourceMint solana.PublicKey
@@ -886,26 +881,26 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
// route/shared_accounts_* (v1) use different account layouts; we only decode args here.
switch {
case bytes.Equal(disc, jupiterRouteV2):
args, err := decodeJupiterV6RouteV2Arg(instruction.Data[8:])
args, err := decodeJupiterV6RouteV2Arg(data[8:])
if err != nil {
return nil, err
}
inputAmount, planCount = pumpSwapSellAtIdx0V2(args.In, args.Plan)
case bytes.Equal(disc, jupiterSharedAccountsRouteV2):
args, err := decodeJupiterV6SharedAccountsRouteV2Arg(instruction.Data[8:])
args, err := decodeJupiterV6SharedAccountsRouteV2Arg(data[8:])
if err != nil {
return nil, err
}
inputAmount, planCount = pumpSwapSellAtIdx0V2(args.In, args.RoutePlan)
case bytes.Equal(disc, jupiterRoute):
args, err := decodeJupiterV6RouteArg(instruction.Data[8:])
args, err := decodeJupiterV6RouteArg(data[8:])
if err != nil {
return nil, err
}
_ = args
inputAmount, planCount = pumpSwapSellAtIdx0(args.In, args.Plan)
case bytes.Equal(disc, jupiterSharedAccountsRoute):
args, err := decodeJupiterV6SharedAccountsRouteArg(instruction.Data[8:])
args, err := decodeJupiterV6SharedAccountsRouteArg(data[8:])
if err != nil {
return nil, err
}
@@ -916,7 +911,8 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
}
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)
logger.Warn("pumpSwapSell at inputIdx=0: multiple instances found", "tx", tx.Signatures(), "planCount", planCount)
return nil, nil
}
if inputAmount == 0 {
return nil, nil
@@ -924,10 +920,10 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
// existing mint extraction logic only valid for route_v2/ exact_out_route_v2. Keep it but guard.
if bytes.Equal(disc, jupiterRouteV2) || bytes.Equal(disc, jupiterSharedAccountsRouteV2) {
if len(instruction.Accounts) < 6 {
if len(accounts) < 6 {
return nil, fmt.Errorf("not enough accounts for jupiter v6 v2 instruction")
}
sourceMint, err = getStaticKey(tx.Message.StaticAccountKeys, int(instruction.Accounts[3]))
sourceMint, err = tx.GetAccount(accounts[3]) //getStaticKey(tx.Message.StaticAccountKeys, int(instruction.Accounts[3]))
if err != nil {
return nil, err
}
@@ -935,12 +931,12 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
var (
srcIdx uint8
)
if len(instruction.Accounts) <= 9 {
if len(accounts) <= 9 {
return nil, nil
}
accounts := instruction.Accounts[8:]
accounts = accounts[8:]
for i, acctIdx := range accounts {
key, err := getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
key, err := tx.GetAccount(acctIdx) // getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
if err != nil {
return nil, err
}
@@ -953,14 +949,14 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
return nil, nil
}
baseMint, err := getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
baseMint, err := tx.GetAccount(accounts[srcIdx]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
if err != nil {
return nil, err
}
if !sourceMint.Equals(baseMint) {
return nil, nil
}
quoteMint, err := getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
quoteMint, err := tx.GetAccount(accounts[srcIdx+1]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
if err != nil {
return nil, err
}
@@ -969,22 +965,22 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
}
} else if bytes.Equal(disc, jupiterSharedAccountsRoute) {
if len(instruction.Accounts) < 12 {
if len(accounts) < 12 {
return nil, fmt.Errorf("not enough accounts for jupiter v6 jupiterSharedAccountsRoute instruction")
}
sourceMint, err = getStaticKey(tx.Message.StaticAccountKeys, int(instruction.Accounts[7]))
sourceMint, err = tx.GetAccount(accounts[7]) // getStaticKey(tx.Message.StaticAccountKeys, int(instruction.Accounts[7]))
if err != nil {
return nil, err
}
var (
srcIdx uint8
)
if len(instruction.Accounts) <= 12 {
if len(accounts) <= 12 {
return nil, nil
}
accounts := instruction.Accounts[11:]
accounts = accounts[11:]
for i, acctIdx := range accounts {
key, err := getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
key, err := tx.GetAccount(acctIdx) // getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
if err != nil {
return nil, err
}
@@ -997,7 +993,7 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
return nil, nil
}
baseMint, err := getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
baseMint, err := tx.GetAccount(accounts[srcIdx]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
if err != nil {
return nil, err
}
@@ -1005,7 +1001,7 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
return nil, nil
}
quoteMint, err := getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
quoteMint, err := tx.GetAccount(accounts[srcIdx+1]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
if err != nil {
return nil, err
}
@@ -1013,16 +1009,16 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
return nil, nil
}
} else {
if len(instruction.Accounts) < 10 {
if len(accounts) < 10 {
return nil, fmt.Errorf("not enough accounts for jupiter v6 jupiterRoute instruction")
}
var (
srcIdx uint8
)
accounts := instruction.Accounts[9:]
accounts = accounts[9:]
for i, acctIdx := range accounts {
key, err := getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
key, err := tx.GetAccount(acctIdx) // getStaticKey(tx.Message.StaticAccountKeys, int(acctIdx))
if err != nil {
return nil, err
}
@@ -1034,12 +1030,12 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
if srcIdx == 0 || srcIdx+1 >= uint8(len(accounts)) {
return nil, nil
}
sourceMint, err = getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
sourceMint, err = tx.GetAccount(accounts[srcIdx]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx]))
if err != nil {
return nil, err
}
quoteMint, err := getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
quoteMint, err := tx.GetAccount(accounts[srcIdx+1]) // getStaticKey(tx.Message.StaticAccountKeys, int(accounts[srcIdx+1]))
if err != nil {
return nil, err
}
@@ -1048,9 +1044,10 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
}
}
maker, _ := tx.GetAccount(0)
signal := &TxSignal{
TxHash: tx.Signatures[0].String(),
Maker: tx.Message.StaticAccountKeys[0].String(),
TxHash: tx.Signatures(),
Maker: maker.String(),
Token0Address: sourceMint.String(),
Token1Address: wsolMint,
Token0Amount: formatTokenAmount(inputAmount),
@@ -1060,7 +1057,7 @@ func parseJupiterV6Instruction(tx *versionedTransaction, instructionIndex int) (
IsToken2022: false,
IsMayhemMode: false,
ExactSOL: false,
Block: tx.Block,
Block: tx.Block(),
Token0AmountUint64: inputAmount,
Token1AmountUint64: 0,
}