3 Commits

Author SHA1 Message Date
75c35f56f1 fix juo v6 pump swap percent 2026-02-17 19:13:12 +08:00
79859bc079 update dflow new action 2026-02-15 20:41:47 +08:00
thloyi
22d2df3782 fix juptierv6 swap kind 2026-02-12 12:44:48 +08:00
4 changed files with 118 additions and 7 deletions

View File

@@ -72,6 +72,11 @@ const (
ActOpenPredictionsOrder ActOpenPredictionsOrder
ActScorchSwap ActScorchSwap
ActIncludeAccount ActIncludeAccount
ActDFLOWStabbleWeightedSwap
ActVertigoSwap
ActSetMinimumLegOutputs
ActSetMinimumLegPrices
) )
// DynamicRouteV1CandidateAction tags // DynamicRouteV1CandidateAction tags
@@ -104,7 +109,7 @@ type dflowSwapParams struct {
// bytes to skip for Action variants; only PumpFun* actions are decoded. // bytes to skip for Action variants; only PumpFun* actions are decoded.
func skipDflowAction(dec *bin.Decoder, tag uint8) (*pumpFunAction, error) { func skipDflowAction(dec *bin.Decoder, tag uint8) (*pumpFunAction, error) {
switch tag { switch tag {
case ActWhirlpoolsSwap, ActClearpoolsSwap, ActWhirlpoolsSwapV2: case ActWhirlpoolsSwap, ActClearpoolsSwap, ActWhirlpoolsSwapV2, ActDFLOWStabbleWeightedSwap, ActVertigoSwap:
// amount u64 + bool + orchestrator_flags u8 // amount u64 + bool + orchestrator_flags u8
return nil, dec.SkipBytes(8 + 1 + 1) return nil, dec.SkipBytes(8 + 1 + 1)
case ActRaydiumAmmSwap, ActLifinityV2Swap, ActObricV2Swap, case ActRaydiumAmmSwap, ActLifinityV2Swap, ActObricV2Swap,
@@ -181,6 +186,19 @@ func skipDflowAction(dec *bin.Decoder, tag uint8) (*pumpFunAction, error) {
return nil, dec.SkipBytes(8 + 16 + 1) return nil, dec.SkipBytes(8 + 16 + 1)
case ActIncludeAccount: case ActIncludeAccount:
return nil, nil return nil, nil
case ActSetMinimumLegOutputs:
ln, err := dec.ReadUint32(binary.LittleEndian)
if err != nil {
return nil, err
}
return nil, dec.SkipBytes(uint(8 * ln))
case ActSetMinimumLegPrices:
// Vec<(u64, u8)>; read length and skip the pairs
ln, err := dec.ReadUint32(binary.LittleEndian)
if err != nil {
return nil, err
}
return nil, dec.SkipBytes(uint(uint64(ln) * (8 + 1)))
default: default:
return nil, fmt.Errorf("unsupported action tag %d", tag) return nil, fmt.Errorf("unsupported action tag %d", tag)
} }

View File

@@ -0,0 +1,61 @@
package shreder
import (
"encoding/hex"
"testing"
)
func TestDFlowDecodedSwapParams(t *testing.T) {
tests := []struct {
name string
hexData string
}{
{
name: "DFlow swap Test 0",
hexData: "f8c69e91e17587c806000000256cb411cd4dcea8c073833936254cc3a7a6f1bc3e1106af1fceaed1bf6d75184d8149476a66d1f0d4c23c177e81d73b8b11297c7f7d8a8d6e339939647915d8096cfcdd170000000093000000300300000000000000000000000000000000000000a84325c4000000002d0decfc36e0bc09000001197bcde00df80000000180130edffead0800000081711ebdc4000000002c013200",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
instrData, err := hex.DecodeString(tt.hexData)
if err != nil {
t.Fatalf("failed to decode hex string: %v", err)
return
}
//t.Logf("raw bytes: %x", instrData[8:])
args, err := decodeSwapParams(instrData[8:])
if err != nil {
t.Fatalf("failed to decode dflow arguments: %v", err)
return
}
t.Logf("decoded args: %+v", args)
})
}
}
func TestDFlowV2DecodedSwapParams(t *testing.T) {
tests := []struct {
name string
hexData string
}{
{
name: "DFlow swap 2 Test 0",
hexData: "414b3f4ceb5b5b880300000025427ee16eed91684faaad4a3f161acd31d92bbc3d1ba0e2ebdb4678448fd5a7aeade9c8b38e8755e811f3373a0056cd5647e4cc3510135f98e97cb03c046ade049d08de17000000007800000023f50a0000000000002e1bfe04000000000001c3e13700000000003601000005",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
instrData, err := hex.DecodeString(tt.hexData)
if err != nil {
t.Fatalf("failed to decode hex string: %v", err)
return
}
args, err := decodeSwap2Params(instrData[8:])
if err != nil {
t.Fatalf("failed to decode dflow arguments: %v", err)
return
}
t.Logf("decoded args: %+v", args)
})
}
}

View File

@@ -157,6 +157,9 @@ const (
PerenaStar PerenaStar
JupiterRfqV2 JupiterRfqV2
GoonFiV2 GoonFiV2
Scorch
VaultLiquidUnstake
XOrca
) )
var swapKindNames = [122]string{"Saber", "SaberAddDecimalsDeposit", "SaberAddDecimalsWithdraw", "TokenSwap", "Sencha", "Step", "Cropper", var swapKindNames = [122]string{"Saber", "SaberAddDecimalsDeposit", "SaberAddDecimalsWithdraw", "TokenSwap", "Sencha", "Step", "Cropper",
@@ -316,7 +319,7 @@ func decodeSwap(dec *bin.Decoder) (Swap, error) {
BoopdotfunWrappedBuy, BoopdotfunWrappedSell, MeteoraDynamicBondingCurveSwapWithRemainingAccounts, BoopdotfunWrappedBuy, BoopdotfunWrappedSell, MeteoraDynamicBondingCurveSwapWithRemainingAccounts,
PumpWrappedBuyV2, PumpWrappedSellV2, PumpSwapBuyV2, PumpSwapSellV2, Aquifer, PumpWrappedBuyV3, PumpWrappedSellV3, PumpWrappedBuyV2, PumpWrappedSellV2, PumpSwapBuyV2, PumpSwapSellV2, Aquifer, PumpWrappedBuyV3, PumpWrappedSellV3,
PumpSwapBuyV3, PumpSwapSellV3, JupiterLendDeposit, JupiterLendRedeem, RaydiumV2, PumpSwapBuyV3, PumpSwapSellV3, JupiterLendDeposit, JupiterLendRedeem, RaydiumV2,
MeteoraDammV2WithRemainingAccounts, Obsidian, PumpWrappedBuyV4, PumpWrappedSellV4, CarrotIssue, CarrotRedeem: MeteoraDammV2WithRemainingAccounts, Obsidian, PumpWrappedBuyV4, PumpWrappedSellV4, CarrotIssue, CarrotRedeem, XOrca:
return out, nil return out, nil
// -------- bool payload -------- // -------- bool payload --------
@@ -406,9 +409,23 @@ func decodeSwap(dec *bin.Decoder) (Swap, error) {
return Swap{}, err return Swap{}, err
} }
return out, nil return out, nil
case Scorch:
// side
if err := skipTwoU64(); err != nil {
return Swap{}, err
}
return out, nil
case VaultLiquidUnstake:
// [{"name":"lst_amounts","type":{"array":["u64",5]}},{"name":"seed","type":"u64"}]
for i := 0; i <= 5; i++ {
if err := skipU64(); err != nil {
return Swap{}, err
}
}
return out, nil
default: default:
// Unknown/new variant: assume no payload (keeps decoder aligned for RoutePlanStepV2 if it really is no-payload). // Unknown/new variant: assume no payload (keeps decoder aligned for RoutePlanStepV2 if it really is no-payload).
return out, nil return out, fmt.Errorf("unknown Swap variant: %d", tag)
} }
} }
@@ -1102,9 +1119,11 @@ func pumpRoutePlanStatsV2(in uint64, out uint64, plan []RoutePlanStepV2, include
func parseJupiterPumpAmmRoute(tx VersionedTransaction, instruction Instructions, in uint64, out uint64, plan []RoutePlanStep) (*TxSignal, bool, error) { func parseJupiterPumpAmmRoute(tx VersionedTransaction, instruction Instructions, in uint64, out uint64, plan []RoutePlanStep) (*TxSignal, bool, error) {
var ( var (
isBuy bool isBuy bool
isSell bool isSell bool
count int count int
sellPercent uint8
buyPercent uint8
) )
for _, step := range plan { for _, step := range plan {
if !isInputIdx0(step.InputIdx) { if !isInputIdx0(step.InputIdx) {
@@ -1113,9 +1132,11 @@ func parseJupiterPumpAmmRoute(tx VersionedTransaction, instruction Instructions,
if isPumpSwapSellKind(step.Swap.Kind) { if isPumpSwapSellKind(step.Swap.Kind) {
isSell = true isSell = true
count++ count++
sellPercent = step.Percent
} else if isPumpSwapBuyKind(step.Swap.Kind) { } else if isPumpSwapBuyKind(step.Swap.Kind) {
isBuy = true isBuy = true
count++ count++
buyPercent = step.Percent
} }
} }
if count == 0 { if count == 0 {
@@ -1137,6 +1158,9 @@ func parseJupiterPumpAmmRoute(tx VersionedTransaction, instruction Instructions,
if in > 0 { if in > 0 {
token0Amount = formatTokenAmount(in) token0Amount = formatTokenAmount(in)
} }
if sellPercent > 0 && sellPercent < 100 {
token0Amount = token0Amount.Mul(decimal.NewFromInt(int64(sellPercent))).Div(decimal.NewFromInt(100))
}
return &TxSignal{ return &TxSignal{
TxHash: tx.Signatures[0].String(), TxHash: tx.Signatures[0].String(),
Maker: tx.StaticAccountKeys[0].String(), Maker: tx.StaticAccountKeys[0].String(),
@@ -1172,6 +1196,10 @@ func parseJupiterPumpAmmRoute(tx VersionedTransaction, instruction Instructions,
if in > 0 { if in > 0 {
token1Amount = formatSolAmount(in) token1Amount = formatSolAmount(in)
} }
if buyPercent > 0 && buyPercent < 100 {
token1Amount = token1Amount.Mul(decimal.NewFromInt(int64(buyPercent))).Div(decimal.NewFromInt(100))
token0Amount = token0Amount.Mul(decimal.NewFromInt(int64(buyPercent))).Div(decimal.NewFromInt(100))
}
return &TxSignal{ return &TxSignal{
TxHash: tx.Signatures[0].String(), TxHash: tx.Signatures[0].String(),
Maker: tx.StaticAccountKeys[0].String(), Maker: tx.StaticAccountKeys[0].String(),

View File

@@ -65,7 +65,11 @@ func TestDecodeRouteArg(t *testing.T) {
}, },
{ {
name: "Jupiter V6 RouteArg Test 1", name: "Jupiter V6 RouteArg Test 1",
hexData: "e517cb977ae3ad2a0200000028640001510000000000000000640102c09ee605000000005e1bc48efa000000d00700", hexData: "e517cb977ae3ad2a03000000646400017ab0b6c3d206f46577050000000c0000526401025f00640203bb628e2902000000338c430100000000320000",
},
{
name: "Jupiter V6 RouteArg Test 2",
hexData: "e517cb977ae3ad2a04000000642300024b00000000410002761acfb15ea9fdcd0501200204769358e96343759bf8014402046196591e1e020000f5bf6fe101000000d00700",
}, },
} }
for _, tt := range tests { for _, tt := range tests {