Update
This commit is contained in:
10
meta.go
10
meta.go
@@ -74,6 +74,16 @@ var (
|
|||||||
meteoraDlmmSwapWithPriceImpactDiscriminator = calculateDiscriminator("global:swap_with_price_impact")
|
meteoraDlmmSwapWithPriceImpactDiscriminator = calculateDiscriminator("global:swap_with_price_impact")
|
||||||
meteoraDlmmSwapWithPriceImpact2Discriminator = calculateDiscriminator("global:swap_with_price_impact2")
|
meteoraDlmmSwapWithPriceImpact2Discriminator = calculateDiscriminator("global:swap_with_price_impact2")
|
||||||
meteoraDlmmSwapEventDiscriminator = calculateDiscriminator("event:Swap")
|
meteoraDlmmSwapEventDiscriminator = calculateDiscriminator("event:Swap")
|
||||||
|
meteoraDlmmAddLiquidityDiscriminator = calculateDiscriminator("global:add_liquidity")
|
||||||
|
meteoraDlmmAddLiquidity2Discriminator = calculateDiscriminator("global:add_liquidity2")
|
||||||
|
meteoraDlmmAddLiquidityByStrategyDiscriminator = calculateDiscriminator("global:add_liquidity_by_strategy")
|
||||||
|
meteoraDlmmAddLiquidityByStrategy2Discriminator = calculateDiscriminator("global:add_liquidity_by_strategy2")
|
||||||
|
meteoraDlmmRemoveLiquidityDiscriminator = calculateDiscriminator("global:remove_liquidity")
|
||||||
|
meteoraDlmmRemoveLiquidity2Discriminator = calculateDiscriminator("global:remove_liquidity2")
|
||||||
|
meteoraDlmmRemoveLiquidityByRangeDiscriminator = calculateDiscriminator("global:remove_liquidity_by_range")
|
||||||
|
meteoraDlmmRemoveLiquidityByRange2Discriminator = calculateDiscriminator("global:remove_liquidity_by_range2")
|
||||||
|
meteoraDlmmAddLiquidityEventDiscriminator = calculateDiscriminator("event:AddLiquidity")
|
||||||
|
meteoraDlmmRemoveLiquidityEventDiscriminator = calculateDiscriminator("event:RemoveLiquidity")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Program PumpAmm program ID
|
// Program PumpAmm program ID
|
||||||
|
|||||||
718
metaoradlmm.go
718
metaoradlmm.go
@@ -39,6 +39,118 @@ type dlmmSwapEvent struct {
|
|||||||
HostFee uint64
|
HostFee uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dlmmAddLiquidityEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
From solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Amounts [2]uint64
|
||||||
|
ActiveBinId int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemoveLiquidityEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
From solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Amounts [2]uint64
|
||||||
|
ActiveBinId int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmBinLiquidityDistribution struct {
|
||||||
|
BinId int32
|
||||||
|
DistributionX uint16
|
||||||
|
DistributionY uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmBinLiquidityReduction struct {
|
||||||
|
BinId int32
|
||||||
|
BpsToRemove uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmLiquidityParameter struct {
|
||||||
|
AmountX uint64
|
||||||
|
AmountY uint64
|
||||||
|
BinLiquidityDist []dlmmBinLiquidityDistribution
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmStrategyParameters struct {
|
||||||
|
MinBinId int32
|
||||||
|
MaxBinId int32
|
||||||
|
StrategyType uint8
|
||||||
|
Parameters [64]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmLiquidityParameterByStrategy struct {
|
||||||
|
AmountX uint64
|
||||||
|
AmountY uint64
|
||||||
|
ActiveID int32
|
||||||
|
MaxActiveBinSlippage int32
|
||||||
|
StrategyParameters dlmmStrategyParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmAddLiquidityArgs struct {
|
||||||
|
LiquidityParameter dlmmLiquidityParameter
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmAddLiquidity2Args struct {
|
||||||
|
LiquidityParameter dlmmLiquidityParameter
|
||||||
|
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmAddLiquidityByStrategyArgs struct {
|
||||||
|
LiquidityParameter dlmmLiquidityParameterByStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmAddLiquidityByStrategy2Args struct {
|
||||||
|
LiquidityParameter dlmmLiquidityParameterByStrategy
|
||||||
|
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemoveLiquidityArgs struct {
|
||||||
|
BinLiquidityRemoval []dlmmBinLiquidityReduction
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemoveLiquidity2Args struct {
|
||||||
|
BinLiquidityRemoval []dlmmBinLiquidityReduction
|
||||||
|
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemoveLiquidityByRangeArgs struct {
|
||||||
|
FromBinId int32
|
||||||
|
ToBinId int32
|
||||||
|
BpsToRemove uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemoveLiquidityByRange2Args struct {
|
||||||
|
FromBinId int32
|
||||||
|
ToBinId int32
|
||||||
|
BpsToRemove uint16
|
||||||
|
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRemainingAccountsInfo struct{}
|
||||||
|
|
||||||
|
func (dlmmRemainingAccountsInfo) UnmarshalWithDecoder(decoder *agbinary.Decoder) error {
|
||||||
|
count, err := decoder.ReadUint32(agbinary.LE)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := uint32(0); i < count; i++ {
|
||||||
|
variant, err := decoder.ReadUint8()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if variant == 3 {
|
||||||
|
if _, err := decoder.ReadUint8(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := decoder.ReadUint8(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type dlmmSwapAccounts struct {
|
type dlmmSwapAccounts struct {
|
||||||
poolIdx int
|
poolIdx int
|
||||||
reserveXIdx int
|
reserveXIdx int
|
||||||
@@ -53,6 +165,20 @@ type dlmmSwapAccounts struct {
|
|||||||
tokenYProgramIdx int
|
tokenYProgramIdx int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dlmmLiquidityAccounts struct {
|
||||||
|
positionIdx int
|
||||||
|
poolIdx int
|
||||||
|
userTokenXIdx int
|
||||||
|
userTokenYIdx int
|
||||||
|
reserveXIdx int
|
||||||
|
reserveYIdx int
|
||||||
|
tokenXMintIdx int
|
||||||
|
tokenYMintIdx int
|
||||||
|
userIdx int
|
||||||
|
tokenXProgramIdx int
|
||||||
|
tokenYProgramIdx int
|
||||||
|
}
|
||||||
|
|
||||||
var meteoraDlmmEventAuthority = func() solana.PublicKey {
|
var meteoraDlmmEventAuthority = func() solana.PublicKey {
|
||||||
key, _, err := solana.FindProgramAddress([][]byte{[]byte("__event_authority")}, meteoraDlmmProgram)
|
key, _, err := solana.FindProgramAddress([][]byte{[]byte("__event_authority")}, meteoraDlmmProgram)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -77,6 +203,12 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI
|
|||||||
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
||||||
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
|
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
|
||||||
return metaoradlmmSwap2Parser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmSwap2Parser(tx, instruction, innerInstructions, offset)
|
||||||
|
case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator,
|
||||||
|
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator:
|
||||||
|
return metaoradlmmAddLiquidityParser(tx, instruction, innerInstructions, offset)
|
||||||
|
case meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator,
|
||||||
|
meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
||||||
|
return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset)
|
||||||
default:
|
default:
|
||||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
}
|
}
|
||||||
@@ -264,6 +396,362 @@ func metaoradlmmSwap2Parser(tx *Tx, instruction Instruction, innerInstructions I
|
|||||||
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||||
|
result := tx.rawTx
|
||||||
|
|
||||||
|
entryContract := result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
|
||||||
|
if instruction.StackHeight != nil && *instruction.StackHeight > 2 {
|
||||||
|
for _, innerInstr := range innerInstructions.Instructions {
|
||||||
|
if innerInstr.StackHeight != nil && *innerInstr.StackHeight == *instruction.StackHeight-1 {
|
||||||
|
entryContract = result.accountList[innerInstr.ProgramIDIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decode := instruction.Data
|
||||||
|
if len(decode) < 8 {
|
||||||
|
offset[1] += 1
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity instruction data too short, offset, %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
discriminator := *(*[8]byte)(decode[:8])
|
||||||
|
var (
|
||||||
|
amountX uint64
|
||||||
|
amountY uint64
|
||||||
|
binDist []dlmmBinLiquidityDistribution
|
||||||
|
startBinId int32
|
||||||
|
endBinId int32
|
||||||
|
hasRange bool
|
||||||
|
)
|
||||||
|
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmAddLiquidityDiscriminator:
|
||||||
|
var args dlmmAddLiquidityArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
amountX = args.LiquidityParameter.AmountX
|
||||||
|
amountY = args.LiquidityParameter.AmountY
|
||||||
|
binDist = args.LiquidityParameter.BinLiquidityDist
|
||||||
|
startBinId, endBinId = dlmmMinMaxBinIdFromDistribution(binDist)
|
||||||
|
hasRange = len(binDist) > 0
|
||||||
|
case meteoraDlmmAddLiquidity2Discriminator:
|
||||||
|
var args dlmmAddLiquidity2Args
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity2 decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
amountX = args.LiquidityParameter.AmountX
|
||||||
|
amountY = args.LiquidityParameter.AmountY
|
||||||
|
binDist = args.LiquidityParameter.BinLiquidityDist
|
||||||
|
startBinId, endBinId = dlmmMinMaxBinIdFromDistribution(binDist)
|
||||||
|
hasRange = len(binDist) > 0
|
||||||
|
case meteoraDlmmAddLiquidityByStrategyDiscriminator:
|
||||||
|
var args dlmmAddLiquidityByStrategyArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity by strategy decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
amountX = args.LiquidityParameter.AmountX
|
||||||
|
amountY = args.LiquidityParameter.AmountY
|
||||||
|
startBinId = args.LiquidityParameter.StrategyParameters.MinBinId
|
||||||
|
endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId
|
||||||
|
hasRange = true
|
||||||
|
case meteoraDlmmAddLiquidityByStrategy2Discriminator:
|
||||||
|
var args dlmmAddLiquidityByStrategy2Args
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity by strategy2 decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
amountX = args.LiquidityParameter.AmountX
|
||||||
|
amountY = args.LiquidityParameter.AmountY
|
||||||
|
startBinId = args.LiquidityParameter.StrategyParameters.MinBinId
|
||||||
|
endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId
|
||||||
|
hasRange = true
|
||||||
|
default:
|
||||||
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := resolveDlmmLiquidityAccounts(result, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
addEvent, nextOffset, err := dlmmAddLiquidityEventFromInnerInstructions(innerInstructions, instruction, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nextOffset, err
|
||||||
|
}
|
||||||
|
offset = nextOffset
|
||||||
|
amountX = addEvent.Amounts[0]
|
||||||
|
amountY = addEvent.Amounts[1]
|
||||||
|
|
||||||
|
binChanges := []DlmmBinLiquidityChange(nil)
|
||||||
|
if len(binDist) > 0 {
|
||||||
|
binChanges = dlmmBinChangesFromDistribution(amountX, amountY, binDist)
|
||||||
|
} else if hasRange {
|
||||||
|
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool := result.accountList[accounts.poolIdx]
|
||||||
|
tokenXMint := result.accountList[accounts.tokenXMintIdx]
|
||||||
|
tokenYMint := result.accountList[accounts.tokenYMintIdx]
|
||||||
|
tokenXProgram := result.accountList[accounts.tokenXProgramIdx]
|
||||||
|
tokenYProgram := result.accountList[accounts.tokenYProgramIdx]
|
||||||
|
|
||||||
|
baseMint, quoteMint, baseIsX := dlmmSelectBaseQuote(tokenXMint, tokenYMint)
|
||||||
|
baseTokenProgram := tokenXProgram
|
||||||
|
quoteTokenProgram := tokenYProgram
|
||||||
|
baseReserveIdx := accounts.reserveXIdx
|
||||||
|
quoteReserveIdx := accounts.reserveYIdx
|
||||||
|
userBaseIdx := accounts.userTokenXIdx
|
||||||
|
userQuoteIdx := accounts.userTokenYIdx
|
||||||
|
if !baseIsX {
|
||||||
|
baseTokenProgram = tokenYProgram
|
||||||
|
quoteTokenProgram = tokenXProgram
|
||||||
|
baseReserveIdx = accounts.reserveYIdx
|
||||||
|
quoteReserveIdx = accounts.reserveXIdx
|
||||||
|
userBaseIdx = accounts.userTokenYIdx
|
||||||
|
userQuoteIdx = accounts.userTokenXIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
amountXDec := decimal.NewFromUint64(amountX)
|
||||||
|
amountYDec := decimal.NewFromUint64(amountY)
|
||||||
|
baseAmount := amountXDec
|
||||||
|
quoteAmount := amountYDec
|
||||||
|
if !baseIsX {
|
||||||
|
baseAmount = amountYDec
|
||||||
|
quoteAmount = amountXDec
|
||||||
|
}
|
||||||
|
|
||||||
|
eventUser := result.accountList[accounts.userIdx]
|
||||||
|
if !addEvent.From.IsZero() {
|
||||||
|
eventUser = addEvent.From
|
||||||
|
}
|
||||||
|
|
||||||
|
baseDecimals, ok := dlmmTokenDecimals(result, baseReserveIdx)
|
||||||
|
if !ok {
|
||||||
|
baseDecimals, _ = dlmmTokenDecimals(result, userBaseIdx)
|
||||||
|
}
|
||||||
|
quoteDecimals, ok := dlmmTokenDecimals(result, quoteReserveIdx)
|
||||||
|
if !ok {
|
||||||
|
quoteDecimals, _ = dlmmTokenDecimals(result, userQuoteIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := tx.Token[baseMint]; !exists && !baseMint.Equals(wSolMint) {
|
||||||
|
tx.Token[baseMint] = TokenMeta{
|
||||||
|
Mint: baseMint,
|
||||||
|
Decimals: baseDecimals,
|
||||||
|
TokenProgram: baseTokenProgram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, exists := tx.Token[quoteMint]; !exists && !quoteMint.Equals(wSolMint) {
|
||||||
|
tx.Token[quoteMint] = TokenMeta{
|
||||||
|
Mint: quoteMint,
|
||||||
|
Decimals: quoteDecimals,
|
||||||
|
TokenProgram: quoteTokenProgram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
baseReserve := getAccountBalanceAfterTx(result, baseReserveIdx)
|
||||||
|
quoteReserve := getAccountBalanceAfterTx(result, quoteReserveIdx)
|
||||||
|
userBase := getAccountBalanceAfterTx(result, userBaseIdx)
|
||||||
|
userQuote := getAccountBalanceAfterTx(result, userQuoteIdx)
|
||||||
|
if quoteMint.Equals(wSolMint) {
|
||||||
|
if solAmount, err := GetSolAfterTx(result, accounts.userIdx); err == nil {
|
||||||
|
userQuote = userQuote.Add(decimal.NewFromUint64(solAmount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap := Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "add_liquidity",
|
||||||
|
Pool: pool,
|
||||||
|
BaseMint: baseMint,
|
||||||
|
QuoteMint: quoteMint,
|
||||||
|
BaseTokenProgram: baseTokenProgram,
|
||||||
|
QuoteTokenProgram: quoteTokenProgram,
|
||||||
|
BaseMintDecimals: baseDecimals,
|
||||||
|
QuoteMintDecimals: quoteDecimals,
|
||||||
|
User: eventUser,
|
||||||
|
BaseAmount: baseAmount,
|
||||||
|
QuoteAmount: quoteAmount,
|
||||||
|
BaseReserve: baseReserve,
|
||||||
|
QuoteReserve: quoteReserve,
|
||||||
|
UserBaseBalance: userBase,
|
||||||
|
UserQuoteBalance: userQuote,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
StartBinId: startBinId,
|
||||||
|
EndBinId: endBinId,
|
||||||
|
BinChanges: binChanges,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []Swap{swap}, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||||
|
result := tx.rawTx
|
||||||
|
|
||||||
|
entryContract := result.accountList[result.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
|
||||||
|
if instruction.StackHeight != nil && *instruction.StackHeight > 2 {
|
||||||
|
for _, innerInstr := range innerInstructions.Instructions {
|
||||||
|
if innerInstr.StackHeight != nil && *innerInstr.StackHeight == *instruction.StackHeight-1 {
|
||||||
|
entryContract = result.accountList[innerInstr.ProgramIDIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decode := instruction.Data
|
||||||
|
if len(decode) < 8 {
|
||||||
|
offset[1] += 1
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity instruction data too short, offset, %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
discriminator := *(*[8]byte)(decode[:8])
|
||||||
|
var (
|
||||||
|
binChanges []DlmmBinLiquidityChange
|
||||||
|
startBinId int32
|
||||||
|
endBinId int32
|
||||||
|
)
|
||||||
|
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmRemoveLiquidityDiscriminator:
|
||||||
|
var args dlmmRemoveLiquidityArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
||||||
|
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
||||||
|
case meteoraDlmmRemoveLiquidity2Discriminator:
|
||||||
|
var args dlmmRemoveLiquidity2Args
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity2 decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
||||||
|
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
||||||
|
case meteoraDlmmRemoveLiquidityByRangeDiscriminator:
|
||||||
|
var args dlmmRemoveLiquidityByRangeArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity by range decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
startBinId = args.FromBinId
|
||||||
|
endBinId = args.ToBinId
|
||||||
|
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
||||||
|
case meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
||||||
|
var args dlmmRemoveLiquidityByRange2Args
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity by range2 decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
startBinId = args.FromBinId
|
||||||
|
endBinId = args.ToBinId
|
||||||
|
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
||||||
|
default:
|
||||||
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := resolveDlmmLiquidityAccounts(result, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEvent, nextOffset, err := dlmmRemoveLiquidityEventFromInnerInstructions(innerInstructions, instruction, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nextOffset, err
|
||||||
|
}
|
||||||
|
offset = nextOffset
|
||||||
|
|
||||||
|
pool := result.accountList[accounts.poolIdx]
|
||||||
|
tokenXMint := result.accountList[accounts.tokenXMintIdx]
|
||||||
|
tokenYMint := result.accountList[accounts.tokenYMintIdx]
|
||||||
|
tokenXProgram := result.accountList[accounts.tokenXProgramIdx]
|
||||||
|
tokenYProgram := result.accountList[accounts.tokenYProgramIdx]
|
||||||
|
|
||||||
|
baseMint, quoteMint, baseIsX := dlmmSelectBaseQuote(tokenXMint, tokenYMint)
|
||||||
|
baseTokenProgram := tokenXProgram
|
||||||
|
quoteTokenProgram := tokenYProgram
|
||||||
|
baseReserveIdx := accounts.reserveXIdx
|
||||||
|
quoteReserveIdx := accounts.reserveYIdx
|
||||||
|
userBaseIdx := accounts.userTokenXIdx
|
||||||
|
userQuoteIdx := accounts.userTokenYIdx
|
||||||
|
if !baseIsX {
|
||||||
|
baseTokenProgram = tokenYProgram
|
||||||
|
quoteTokenProgram = tokenXProgram
|
||||||
|
baseReserveIdx = accounts.reserveYIdx
|
||||||
|
quoteReserveIdx = accounts.reserveXIdx
|
||||||
|
userBaseIdx = accounts.userTokenYIdx
|
||||||
|
userQuoteIdx = accounts.userTokenXIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
amountXDec := decimal.NewFromUint64(removeEvent.Amounts[0])
|
||||||
|
amountYDec := decimal.NewFromUint64(removeEvent.Amounts[1])
|
||||||
|
baseAmount := amountXDec
|
||||||
|
quoteAmount := amountYDec
|
||||||
|
if !baseIsX {
|
||||||
|
baseAmount = amountYDec
|
||||||
|
quoteAmount = amountXDec
|
||||||
|
}
|
||||||
|
|
||||||
|
eventUser := result.accountList[accounts.userIdx]
|
||||||
|
if !removeEvent.From.IsZero() {
|
||||||
|
eventUser = removeEvent.From
|
||||||
|
}
|
||||||
|
|
||||||
|
baseDecimals, ok := dlmmTokenDecimals(result, baseReserveIdx)
|
||||||
|
if !ok {
|
||||||
|
baseDecimals, _ = dlmmTokenDecimals(result, userBaseIdx)
|
||||||
|
}
|
||||||
|
quoteDecimals, ok := dlmmTokenDecimals(result, quoteReserveIdx)
|
||||||
|
if !ok {
|
||||||
|
quoteDecimals, _ = dlmmTokenDecimals(result, userQuoteIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := tx.Token[baseMint]; !exists && !baseMint.Equals(wSolMint) {
|
||||||
|
tx.Token[baseMint] = TokenMeta{
|
||||||
|
Mint: baseMint,
|
||||||
|
Decimals: baseDecimals,
|
||||||
|
TokenProgram: baseTokenProgram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, exists := tx.Token[quoteMint]; !exists && !quoteMint.Equals(wSolMint) {
|
||||||
|
tx.Token[quoteMint] = TokenMeta{
|
||||||
|
Mint: quoteMint,
|
||||||
|
Decimals: quoteDecimals,
|
||||||
|
TokenProgram: quoteTokenProgram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
baseReserve := getAccountBalanceAfterTx(result, baseReserveIdx)
|
||||||
|
quoteReserve := getAccountBalanceAfterTx(result, quoteReserveIdx)
|
||||||
|
userBase := getAccountBalanceAfterTx(result, userBaseIdx)
|
||||||
|
userQuote := getAccountBalanceAfterTx(result, userQuoteIdx)
|
||||||
|
if quoteMint.Equals(wSolMint) {
|
||||||
|
if solAmount, err := GetSolAfterTx(result, accounts.userIdx); err == nil {
|
||||||
|
userQuote = userQuote.Add(decimal.NewFromUint64(solAmount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap := Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "remove_liquidity",
|
||||||
|
Pool: pool,
|
||||||
|
BaseMint: baseMint,
|
||||||
|
QuoteMint: quoteMint,
|
||||||
|
BaseTokenProgram: baseTokenProgram,
|
||||||
|
QuoteTokenProgram: quoteTokenProgram,
|
||||||
|
BaseMintDecimals: baseDecimals,
|
||||||
|
QuoteMintDecimals: quoteDecimals,
|
||||||
|
User: eventUser,
|
||||||
|
BaseAmount: baseAmount,
|
||||||
|
QuoteAmount: quoteAmount,
|
||||||
|
BaseReserve: baseReserve,
|
||||||
|
QuoteReserve: quoteReserve,
|
||||||
|
UserBaseBalance: userBase,
|
||||||
|
UserQuoteBalance: userQuote,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
StartBinId: startBinId,
|
||||||
|
EndBinId: endBinId,
|
||||||
|
BinChanges: binChanges,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []Swap{swap}, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
func dlmmSelectBaseQuote(tokenX, tokenY solana.PublicKey) (baseMint solana.PublicKey, quoteMint solana.PublicKey, baseIsX bool) {
|
func dlmmSelectBaseQuote(tokenX, tokenY solana.PublicKey) (baseMint solana.PublicKey, quoteMint solana.PublicKey, baseIsX bool) {
|
||||||
priority := []solana.PublicKey{wSolMint, usdcMint, usd1Mint}
|
priority := []solana.PublicKey{wSolMint, usdcMint, usd1Mint}
|
||||||
for _, mint := range priority {
|
for _, mint := range priority {
|
||||||
@@ -301,6 +789,54 @@ func dlmmSwapEventFromInnerInstructions(innerInstructions InnerInstructions, ins
|
|||||||
return dlmmSwapEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm swap event not found, offset, %d, %d", offset[0], prefixLen)
|
return dlmmSwapEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm swap event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmAddLiquidityEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmAddLiquidityEvent, [2]uint, error) {
|
||||||
|
var prefixLen = offset[1]
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, prefixLen)
|
||||||
|
if err != nil {
|
||||||
|
return dlmmAddLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity get inner instructions error: %v, offset, %d, %d", err, offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
for innerIndex, innerInstr := range inners {
|
||||||
|
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event, ok := dlmmDecodeAddLiquidityEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] += uint(innerIndex) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, nil
|
||||||
|
}
|
||||||
|
return dlmmAddLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmRemoveLiquidityEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmRemoveLiquidityEvent, [2]uint, error) {
|
||||||
|
var prefixLen = offset[1]
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, prefixLen)
|
||||||
|
if err != nil {
|
||||||
|
return dlmmRemoveLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity get inner instructions error: %v, offset, %d, %d", err, offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
for innerIndex, innerInstr := range inners {
|
||||||
|
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event, ok := dlmmDecodeRemoveLiquidityEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] += uint(innerIndex) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, nil
|
||||||
|
}
|
||||||
|
return dlmmRemoveLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
|
||||||
func dlmmDecodeSwapEvent(data []byte) (dlmmSwapEvent, bool) {
|
func dlmmDecodeSwapEvent(data []byte) (dlmmSwapEvent, bool) {
|
||||||
switch {
|
switch {
|
||||||
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmSwapEventDiscriminator[:]):
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmSwapEventDiscriminator[:]):
|
||||||
@@ -322,6 +858,48 @@ func dlmmDecodeSwapEvent(data []byte) (dlmmSwapEvent, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmDecodeAddLiquidityEvent(data []byte) (dlmmAddLiquidityEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmAddLiquidityEventDiscriminator[:]):
|
||||||
|
var event dlmmAddLiquidityEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[8:]).Decode(&event); err != nil {
|
||||||
|
return dlmmAddLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmAddLiquidityEventDiscriminator[:]):
|
||||||
|
var event dlmmAddLiquidityEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmAddLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
default:
|
||||||
|
return dlmmAddLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmDecodeRemoveLiquidityEvent(data []byte) (dlmmRemoveLiquidityEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmRemoveLiquidityEventDiscriminator[:]):
|
||||||
|
var event dlmmRemoveLiquidityEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[8:]).Decode(&event); err != nil {
|
||||||
|
return dlmmRemoveLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmRemoveLiquidityEventDiscriminator[:]):
|
||||||
|
var event dlmmRemoveLiquidityEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmRemoveLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
default:
|
||||||
|
return dlmmRemoveLiquidityEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func resolveDlmmSwapAccounts(result *RawTx, accounts []int) (dlmmSwapAccounts, error) {
|
func resolveDlmmSwapAccounts(result *RawTx, accounts []int) (dlmmSwapAccounts, error) {
|
||||||
if len(accounts) < 13 {
|
if len(accounts) < 13 {
|
||||||
return dlmmSwapAccounts{}, fmt.Errorf("accounts too short, expected at least 13")
|
return dlmmSwapAccounts{}, fmt.Errorf("accounts too short, expected at least 13")
|
||||||
@@ -385,6 +963,60 @@ func resolveDlmmSwapAccounts(result *RawTx, accounts []int) (dlmmSwapAccounts, e
|
|||||||
return dlmmSwapAccounts{}, fmt.Errorf("accounts layout invalid")
|
return dlmmSwapAccounts{}, fmt.Errorf("accounts layout invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveDlmmLiquidityAccounts(result *RawTx, accounts []int) (dlmmLiquidityAccounts, error) {
|
||||||
|
if len(accounts) < 9 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("accounts too short, expected at least 9")
|
||||||
|
}
|
||||||
|
accountList := result.accountList
|
||||||
|
|
||||||
|
eventAuthorityPos := -1
|
||||||
|
for i, idx := range accounts {
|
||||||
|
if idx < 0 || idx >= len(accountList) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if accountList[idx].Equals(meteoraDlmmEventAuthority) {
|
||||||
|
eventAuthorityPos = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if eventAuthorityPos == -1 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("event authority not found")
|
||||||
|
}
|
||||||
|
if eventAuthorityPos+1 >= len(accounts) || !accountList[accounts[eventAuthorityPos+1]].Equals(meteoraDlmmProgram) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("program id not found after event authority")
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenYProgramPos := eventAuthorityPos - 1
|
||||||
|
if tokenYProgramPos < 0 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("token program position invalid")
|
||||||
|
}
|
||||||
|
if accountList[accounts[tokenYProgramPos]].Equals(solana.MemoProgramID) {
|
||||||
|
tokenYProgramPos--
|
||||||
|
}
|
||||||
|
if tokenYProgramPos < 1 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("token program positions invalid")
|
||||||
|
}
|
||||||
|
tokenXProgramPos := tokenYProgramPos - 1
|
||||||
|
userPos := tokenXProgramPos - 1
|
||||||
|
if userPos < 0 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("user position invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
return dlmmLiquidityAccounts{
|
||||||
|
positionIdx: accounts[0],
|
||||||
|
poolIdx: accounts[1],
|
||||||
|
userTokenXIdx: accounts[3],
|
||||||
|
userTokenYIdx: accounts[4],
|
||||||
|
reserveXIdx: accounts[5],
|
||||||
|
reserveYIdx: accounts[6],
|
||||||
|
tokenXMintIdx: accounts[7],
|
||||||
|
tokenYMintIdx: accounts[8],
|
||||||
|
userIdx: accounts[userPos],
|
||||||
|
tokenXProgramIdx: accounts[tokenXProgramPos],
|
||||||
|
tokenYProgramIdx: accounts[tokenYProgramPos],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func dlmmTokenDecimals(result *RawTx, accountIndex int) (uint8, bool) {
|
func dlmmTokenDecimals(result *RawTx, accountIndex int) (uint8, bool) {
|
||||||
for _, meta := range result.Meta.PostTokenBalances {
|
for _, meta := range result.Meta.PostTokenBalances {
|
||||||
if meta.AccountIndex == accountIndex {
|
if meta.AccountIndex == accountIndex {
|
||||||
@@ -468,3 +1100,89 @@ func dlmmTokenBalanceMeta(result *RawTx, accountIndex int) (TokenBalance, bool)
|
|||||||
}
|
}
|
||||||
return TokenBalance{}, false
|
return TokenBalance{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmBinChangesFromDistribution(amountX, amountY uint64, dist []dlmmBinLiquidityDistribution) []DlmmBinLiquidityChange {
|
||||||
|
if len(dist) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
totalX := decimal.NewFromUint64(amountX)
|
||||||
|
totalY := decimal.NewFromUint64(amountY)
|
||||||
|
denom := decimal.NewFromInt(10000)
|
||||||
|
changes := make([]DlmmBinLiquidityChange, 0, len(dist))
|
||||||
|
for _, item := range dist {
|
||||||
|
x := totalX.Mul(decimal.NewFromInt(int64(item.DistributionX))).Div(denom).Truncate(0)
|
||||||
|
y := totalY.Mul(decimal.NewFromInt(int64(item.DistributionY))).Div(denom).Truncate(0)
|
||||||
|
changes = append(changes, DlmmBinLiquidityChange{
|
||||||
|
BinId: item.BinId,
|
||||||
|
AmountX: x,
|
||||||
|
AmountY: y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmBinChangesFromReduction(reduction []dlmmBinLiquidityReduction) []DlmmBinLiquidityChange {
|
||||||
|
if len(reduction) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
changes := make([]DlmmBinLiquidityChange, 0, len(reduction))
|
||||||
|
for _, item := range reduction {
|
||||||
|
changes = append(changes, DlmmBinLiquidityChange{
|
||||||
|
BinId: item.BinId,
|
||||||
|
BpsToRemove: item.BpsToRemove,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmBinChangesFromRange(startBinId, endBinId int32, bpsToRemove uint16) []DlmmBinLiquidityChange {
|
||||||
|
if startBinId > endBinId {
|
||||||
|
startBinId, endBinId = endBinId, startBinId
|
||||||
|
}
|
||||||
|
count := int(endBinId-startBinId) + 1
|
||||||
|
if count <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
changes := make([]DlmmBinLiquidityChange, 0, count)
|
||||||
|
for binId := startBinId; binId <= endBinId; binId++ {
|
||||||
|
changes = append(changes, DlmmBinLiquidityChange{
|
||||||
|
BinId: binId,
|
||||||
|
BpsToRemove: bpsToRemove,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmMinMaxBinIdFromDistribution(dist []dlmmBinLiquidityDistribution) (int32, int32) {
|
||||||
|
if len(dist) == 0 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
min := dist[0].BinId
|
||||||
|
max := dist[0].BinId
|
||||||
|
for _, item := range dist[1:] {
|
||||||
|
if item.BinId < min {
|
||||||
|
min = item.BinId
|
||||||
|
}
|
||||||
|
if item.BinId > max {
|
||||||
|
max = item.BinId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min, max
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmMinMaxBinIdFromReduction(reduction []dlmmBinLiquidityReduction) (int32, int32) {
|
||||||
|
if len(reduction) == 0 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
min := reduction[0].BinId
|
||||||
|
max := reduction[0].BinId
|
||||||
|
for _, item := range reduction[1:] {
|
||||||
|
if item.BinId < min {
|
||||||
|
min = item.BinId
|
||||||
|
}
|
||||||
|
if item.BinId > max {
|
||||||
|
max = item.BinId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min, max
|
||||||
|
}
|
||||||
|
|||||||
8
tx.go
8
tx.go
@@ -37,6 +37,14 @@ type Swap struct {
|
|||||||
//For meteora dlmm
|
//For meteora dlmm
|
||||||
StartBinId int32
|
StartBinId int32
|
||||||
EndBinId int32
|
EndBinId int32
|
||||||
|
BinChanges []DlmmBinLiquidityChange
|
||||||
|
}
|
||||||
|
|
||||||
|
type DlmmBinLiquidityChange struct {
|
||||||
|
BinId int32
|
||||||
|
AmountX decimal.Decimal
|
||||||
|
AmountY decimal.Decimal
|
||||||
|
BpsToRemove uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type platformInfo struct {
|
type platformInfo struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user