swap amount input

This commit is contained in:
thloyi
2026-04-16 14:24:14 +08:00
parent ab0e87a48a
commit e761fd6f84
29 changed files with 1542 additions and 214 deletions

View File

@@ -1,12 +1,33 @@
package pump_parser
import (
"encoding/binary"
"fmt"
"github.com/gagliardetto/solana-go"
"github.com/shopspring/decimal"
)
func decodeOrcaWhirlpoolSwapArgs(data []byte) (amount uint64, otherAmountThreshold uint64, amountSpecifiedIsInput bool, err error) {
if len(data) < 42 {
return 0, 0, false, fmt.Errorf("orca whirlpool swap instruction data too short")
}
amount = binary.LittleEndian.Uint64(data[8:16])
otherAmountThreshold = binary.LittleEndian.Uint64(data[16:24])
amountSpecifiedIsInput = data[40] != 0
return amount, otherAmountThreshold, amountSpecifiedIsInput, nil
}
func decodeOrcaWhirlpoolTwoHopSwapArgs(data []byte) (amount uint64, otherAmountThreshold uint64, amountSpecifiedIsInput bool, err error) {
if len(data) < 27 {
return 0, 0, false, fmt.Errorf("orca whirlpool two-hop swap instruction data too short")
}
amount = binary.LittleEndian.Uint64(data[8:16])
otherAmountThreshold = binary.LittleEndian.Uint64(data[16:24])
amountSpecifiedIsInput = data[24] != 0
return amount, otherAmountThreshold, amountSpecifiedIsInput, nil
}
func orcaWhirPoolParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
if !tx.rawTx.accountList[instruction.ProgramIDIndex].Equals(orcaProgramID) {
return nil, increaseOffset(offset), fmt.Errorf("orcawhirpoolprogram instruction not found, offset, %d, %d", offset[0], offset[1])
@@ -709,6 +730,14 @@ func orcaWhirPoolSwapParser(tx *Tx, instruction Instruction, innerInstructions I
}
var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
amount, otherAmountThreshold, amountSpecifiedIsInput, err := decodeOrcaWhirlpoolSwapArgs(instruction.Data)
if err != nil {
return nil, increaseOffset(offset), err
}
swapMode := SwapModeExactOut
if amountSpecifiedIsInput {
swapMode = SwapModeExactIn
}
user := tx.rawTx.accountList[instruction.Accounts[1]]
pool := tx.rawTx.accountList[instruction.Accounts[2]]
@@ -781,8 +810,7 @@ func orcaWhirPoolSwapParser(tx *Tx, instruction Instruction, innerInstructions I
return nil, offset, fmt.Errorf("orca whirpool swap failed to find both base and quote token transfer in inner instructions")
}
return []Swap{
{
swap := Swap{
Program: SolProgramOrcaWhirPool,
Event: event,
Pool: pool,
@@ -800,8 +828,10 @@ func orcaWhirPoolSwapParser(tx *Tx, instruction Instruction, innerInstructions I
UserQuoteBalance: userQuote,
User: user,
EntryContract: entryContract,
},
}, offset, nil
}
swap.SetSwapAmountInfo(swapMode, decimal.NewFromUint64(amount), decimal.NewFromUint64(otherAmountThreshold))
return []Swap{swap}, offset, nil
}
func orcaWhirPoolSwapV2Parser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
@@ -810,6 +840,14 @@ func orcaWhirPoolSwapV2Parser(tx *Tx, instruction Instruction, innerInstructions
}
var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
amount, otherAmountThreshold, amountSpecifiedIsInput, err := decodeOrcaWhirlpoolSwapArgs(instruction.Data)
if err != nil {
return nil, increaseOffset(offset), err
}
swapMode := SwapModeExactOut
if amountSpecifiedIsInput {
swapMode = SwapModeExactIn
}
user := tx.rawTx.accountList[instruction.Accounts[3]]
pool := tx.rawTx.accountList[instruction.Accounts[4]]
@@ -883,8 +921,7 @@ func orcaWhirPoolSwapV2Parser(tx *Tx, instruction Instruction, innerInstructions
}
offset[1] += uint(skipOffset + 1)
return []Swap{
{
swap := Swap{
Program: SolProgramOrcaWhirPool,
Event: event,
Pool: pool,
@@ -902,8 +939,10 @@ func orcaWhirPoolSwapV2Parser(tx *Tx, instruction Instruction, innerInstructions
UserQuoteBalance: userQuote,
User: user,
EntryContract: entryContract,
},
}, offset, nil
}
swap.SetSwapAmountInfo(swapMode, decimal.NewFromUint64(amount), decimal.NewFromUint64(otherAmountThreshold))
return []Swap{swap}, offset, nil
}
func orcaWhirPoolTwoHopSwapParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
@@ -912,6 +951,14 @@ func orcaWhirPoolTwoHopSwapParser(tx *Tx, instruction Instruction, innerInstruct
}
var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
amountSpecified, otherAmountThreshold, amountSpecifiedIsInput, err := decodeOrcaWhirlpoolTwoHopSwapArgs(instruction.Data)
if err != nil {
return nil, increaseOffset(offset), err
}
swapMode := SwapModeExactOut
if amountSpecifiedIsInput {
swapMode = SwapModeExactIn
}
user := tx.rawTx.accountList[instruction.Accounts[1]]
pool1 := tx.rawTx.accountList[instruction.Accounts[2]]
@@ -1082,6 +1129,29 @@ func orcaWhirPoolTwoHopSwapParser(tx *Tx, instruction Instruction, innerInstruct
EntryContract: entryContract,
}
}
fixedSide := fixedSwapAmountSide(swaps[0].Event, swapMode)
fixedMint := swapMintForSide(swaps[0].BaseMint, swaps[0].QuoteMint, fixedSide)
limitSide := oppositeSwapAmountSide(fixedSide)
limitMint := swapMintForSide(swaps[1].BaseMint, swaps[1].QuoteMint, limitSide)
actualLimitAmount := swapAmountForSide(swaps[1].BaseAmount, swaps[1].QuoteAmount, limitSide)
if swapMode == SwapModeExactOut {
fixedSide = fixedSwapAmountSide(swaps[1].Event, swapMode)
fixedMint = swapMintForSide(swaps[1].BaseMint, swaps[1].QuoteMint, fixedSide)
limitSide = oppositeSwapAmountSide(fixedSwapAmountSide(swaps[0].Event, swapMode))
limitMint = swapMintForSide(swaps[0].BaseMint, swaps[0].QuoteMint, limitSide)
actualLimitAmount = swapAmountForSide(swaps[0].BaseAmount, swaps[0].QuoteAmount, limitSide)
}
swaps[0].SetSwapAmountInfoDetailed(
swapMode,
decimal.NewFromUint64(amountSpecified),
fixedSide,
fixedMint,
limitSwapAmountType(swapMode),
decimal.NewFromUint64(otherAmountThreshold),
limitSide,
limitMint,
actualLimitAmount,
)
return swaps, offset, nil
}
@@ -1091,6 +1161,14 @@ func orcaWhirPoolTwoHopSwapV2Parser(tx *Tx, instruction Instruction, innerInstru
}
var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
amountSpecified, otherAmountThreshold, amountSpecifiedIsInput, err := decodeOrcaWhirlpoolTwoHopSwapArgs(instruction.Data)
if err != nil {
return nil, increaseOffset(offset), err
}
swapMode := SwapModeExactOut
if amountSpecifiedIsInput {
swapMode = SwapModeExactIn
}
user := tx.rawTx.accountList[instruction.Accounts[14]]
pool1 := tx.rawTx.accountList[instruction.Accounts[0]]
@@ -1258,5 +1336,28 @@ func orcaWhirPoolTwoHopSwapV2Parser(tx *Tx, instruction Instruction, innerInstru
EntryContract: entryContract,
}
}
fixedSide := fixedSwapAmountSide(swaps[0].Event, swapMode)
fixedMint := swapMintForSide(swaps[0].BaseMint, swaps[0].QuoteMint, fixedSide)
limitSide := oppositeSwapAmountSide(fixedSide)
limitMint := swapMintForSide(swaps[1].BaseMint, swaps[1].QuoteMint, limitSide)
actualLimitAmount := swapAmountForSide(swaps[1].BaseAmount, swaps[1].QuoteAmount, limitSide)
if swapMode == SwapModeExactOut {
fixedSide = fixedSwapAmountSide(swaps[1].Event, swapMode)
fixedMint = swapMintForSide(swaps[1].BaseMint, swaps[1].QuoteMint, fixedSide)
limitSide = oppositeSwapAmountSide(fixedSwapAmountSide(swaps[0].Event, swapMode))
limitMint = swapMintForSide(swaps[0].BaseMint, swaps[0].QuoteMint, limitSide)
actualLimitAmount = swapAmountForSide(swaps[0].BaseAmount, swaps[0].QuoteAmount, limitSide)
}
swaps[0].SetSwapAmountInfoDetailed(
swapMode,
decimal.NewFromUint64(amountSpecified),
fixedSide,
fixedMint,
limitSwapAmountType(swapMode),
decimal.NewFromUint64(otherAmountThreshold),
limitSide,
limitMint,
actualLimitAmount,
)
return swaps, offset, nil
}