Compare commits

..

4 Commits

Author SHA1 Message Date
bijianing97
d9a214b4b4 Add dlmm add liquidity one side function 2026-03-25 11:34:46 +08:00
thloyi
047b549d0f option ComputeUnitsConsumed 2026-03-23 20:20:21 +08:00
bijianing97
9327eab010 Fix dlmm parser 2026-03-23 15:30:43 +08:00
bijianing97
0ef57cf79a Add dlmm add_liquidity_by_weight 2026-03-20 17:06:37 +08:00
3 changed files with 386 additions and 47 deletions

74
meta.go
View File

@@ -68,40 +68,46 @@ var (
) )
var ( var (
meteoraInitializeLbPairDiscriminator = calculateDiscriminator("global:initialize_lb_pair2") meteoraInitializeLbPairDiscriminator = calculateDiscriminator("global:initialize_lb_pair2")
meteoraInitializeLbPairEventDiscriminator = calculateDiscriminator("event:LbPairCreate") meteoraInitializeLbPairEventDiscriminator = calculateDiscriminator("event:LbPairCreate")
meteoraDlmmSwapDiscriminator = calculateDiscriminator("global:swap") meteoraDlmmSwapDiscriminator = calculateDiscriminator("global:swap")
meteoraDlmmSwap2Discriminator = calculateDiscriminator("global:swap2") meteoraDlmmSwap2Discriminator = calculateDiscriminator("global:swap2")
meteoraDlmmSwapExactOutDiscriminator = calculateDiscriminator("global:swap_exact_out") meteoraDlmmSwapExactOutDiscriminator = calculateDiscriminator("global:swap_exact_out")
meteoraDlmmSwapExactOut2Discriminator = calculateDiscriminator("global:swap_exact_out2") meteoraDlmmSwapExactOut2Discriminator = calculateDiscriminator("global:swap_exact_out2")
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")
meteoraDlmmInitializePositionDiscriminator = calculateDiscriminator("global:initialize_position") meteoraDlmmInitializePositionDiscriminator = calculateDiscriminator("global:initialize_position")
meteoraDlmmInitializePosition2Discriminator = calculateDiscriminator("global:initialize_position2") meteoraDlmmInitializePosition2Discriminator = calculateDiscriminator("global:initialize_position2")
meteoraDlmmInitializePositionByOperatorDiscriminator = calculateDiscriminator("global:initialize_position_by_operator") meteoraDlmmInitializePositionByOperatorDiscriminator = calculateDiscriminator("global:initialize_position_by_operator")
meteoraDlmmInitializePositionPdaDiscriminator = calculateDiscriminator("global:initialize_position_pda") meteoraDlmmInitializePositionPdaDiscriminator = calculateDiscriminator("global:initialize_position_pda")
meteoraDlmmClosePositionDiscriminator = calculateDiscriminator("global:close_position") meteoraDlmmClosePositionDiscriminator = calculateDiscriminator("global:close_position")
meteoraDlmmClosePosition2Discriminator = calculateDiscriminator("global:close_position2") meteoraDlmmClosePosition2Discriminator = calculateDiscriminator("global:close_position2")
meteoraDlmmClosePositionIfEmptyDiscriminator = calculateDiscriminator("global:close_position_if_empty") meteoraDlmmClosePositionIfEmptyDiscriminator = calculateDiscriminator("global:close_position_if_empty")
meteoraDlmmSwapEventDiscriminator = calculateDiscriminator("event:Swap") meteoraDlmmSwapEventDiscriminator = calculateDiscriminator("event:Swap")
meteoraDlmmAddLiquidityDiscriminator = calculateDiscriminator("global:add_liquidity") meteoraDlmmAddLiquidityDiscriminator = calculateDiscriminator("global:add_liquidity")
meteoraDlmmAddLiquidity2Discriminator = calculateDiscriminator("global:add_liquidity2") meteoraDlmmAddLiquidity2Discriminator = calculateDiscriminator("global:add_liquidity2")
meteoraDlmmAddLiquidityByStrategyDiscriminator = calculateDiscriminator("global:add_liquidity_by_strategy") meteoraDlmmAddLiquidityByStrategyDiscriminator = calculateDiscriminator("global:add_liquidity_by_strategy")
meteoraDlmmAddLiquidityByStrategy2Discriminator = calculateDiscriminator("global:add_liquidity_by_strategy2") meteoraDlmmAddLiquidityByStrategy2Discriminator = calculateDiscriminator("global:add_liquidity_by_strategy2")
meteoraDlmmClaimFeeDiscriminator = calculateDiscriminator("global:claim_fee") meteoraDlmmAddLiquidityByWeightDiscriminator = calculateDiscriminator("global:add_liquidity_by_weight")
meteoraDlmmClaimFee2Discriminator = calculateDiscriminator("global:claim_fee2") meteoraDlmmAddLiquidityOneSideDiscriminator = calculateDiscriminator("global:add_liquidity_one_side")
meteoraDlmmRebalanceLiquidityDiscriminator = calculateDiscriminator("global:rebalance_liquidity") meteoraDlmmAddLiquidityOneSidePreciseDiscriminator = calculateDiscriminator("global:add_liquidity_one_side_precise")
meteoraDlmmRemoveLiquidityDiscriminator = calculateDiscriminator("global:remove_liquidity") meteoraDlmmAddLiquidityOneSidePrecise2Discriminator = calculateDiscriminator("global:add_liquidity_one_side_precise2")
meteoraDlmmRemoveLiquidity2Discriminator = calculateDiscriminator("global:remove_liquidity2") meteoraDlmmAddLiquidityByStrategyOneSideDiscriminator = calculateDiscriminator("global:add_liquidity_by_strategy_one_side")
meteoraDlmmRemoveLiquidityByRangeDiscriminator = calculateDiscriminator("global:remove_liquidity_by_range") meteoraDlmmClaimFeeDiscriminator = calculateDiscriminator("global:claim_fee")
meteoraDlmmRemoveLiquidityByRange2Discriminator = calculateDiscriminator("global:remove_liquidity_by_range2") meteoraDlmmClaimFee2Discriminator = calculateDiscriminator("global:claim_fee2")
meteoraDlmmAddLiquidityEventDiscriminator = calculateDiscriminator("event:AddLiquidity") meteoraDlmmRebalanceLiquidityDiscriminator = calculateDiscriminator("global:rebalance_liquidity")
meteoraDlmmClaimFeeEventDiscriminator = calculateDiscriminator("event:ClaimFee") meteoraDlmmRemoveAllLiquidityDiscriminator = calculateDiscriminator("global:remove_all_liquidity")
meteoraDlmmClaimFee2EventDiscriminator = calculateDiscriminator("event:ClaimFee2") meteoraDlmmRemoveLiquidityDiscriminator = calculateDiscriminator("global:remove_liquidity")
meteoraDlmmPositionCloseEventDiscriminator = calculateDiscriminator("event:PositionClose") meteoraDlmmRemoveLiquidity2Discriminator = calculateDiscriminator("global:remove_liquidity2")
meteoraDlmmPositionCreateEventDiscriminator = calculateDiscriminator("event:PositionCreate") meteoraDlmmRemoveLiquidityByRangeDiscriminator = calculateDiscriminator("global:remove_liquidity_by_range")
meteoraDlmmRebalancingEventDiscriminator = calculateDiscriminator("event:Rebalancing") meteoraDlmmRemoveLiquidityByRange2Discriminator = calculateDiscriminator("global:remove_liquidity_by_range2")
meteoraDlmmRemoveLiquidityEventDiscriminator = calculateDiscriminator("event:RemoveLiquidity") meteoraDlmmAddLiquidityEventDiscriminator = calculateDiscriminator("event:AddLiquidity")
meteoraDlmmClaimFeeEventDiscriminator = calculateDiscriminator("event:ClaimFee")
meteoraDlmmClaimFee2EventDiscriminator = calculateDiscriminator("event:ClaimFee2")
meteoraDlmmPositionCloseEventDiscriminator = calculateDiscriminator("event:PositionClose")
meteoraDlmmPositionCreateEventDiscriminator = calculateDiscriminator("event:PositionCreate")
meteoraDlmmRebalancingEventDiscriminator = calculateDiscriminator("event:Rebalancing")
meteoraDlmmRemoveLiquidityEventDiscriminator = calculateDiscriminator("event:RemoveLiquidity")
) )
var ( var (

View File

@@ -117,6 +117,11 @@ type dlmmBinLiquidityDistribution struct {
DistributionY uint16 DistributionY uint16
} }
type dlmmBinLiquidityDistributionByWeight struct {
BinId int32
Weight uint16
}
type dlmmBinLiquidityReduction struct { type dlmmBinLiquidityReduction struct {
BinId int32 BinId int32
BpsToRemove uint16 BpsToRemove uint16
@@ -143,6 +148,14 @@ type dlmmLiquidityParameterByStrategy struct {
StrategyParameters dlmmStrategyParameters StrategyParameters dlmmStrategyParameters
} }
type dlmmLiquidityParameterByWeight struct {
AmountX uint64
AmountY uint64
ActiveID int32
MaxActiveBinSlippage int32
BinLiquidityDist []dlmmBinLiquidityDistributionByWeight
}
type dlmmAddLiquidityArgs struct { type dlmmAddLiquidityArgs struct {
LiquidityParameter dlmmLiquidityParameter LiquidityParameter dlmmLiquidityParameter
} }
@@ -161,6 +174,57 @@ type dlmmAddLiquidityByStrategy2Args struct {
RemainingAccountsInfo dlmmRemainingAccountsInfo RemainingAccountsInfo dlmmRemainingAccountsInfo
} }
type dlmmAddLiquidityByWeightArgs struct {
LiquidityParameter dlmmLiquidityParameterByWeight
}
type dlmmLiquidityOneSideParameter struct {
Amount uint64
ActiveID int32
MaxActiveBinSlippage int32
BinLiquidityDist []dlmmBinLiquidityDistributionByWeight
}
type dlmmLiquidityParameterByStrategyOneSide struct {
Amount uint64
ActiveID int32
MaxActiveBinSlippage int32
StrategyParameters dlmmStrategyParameters
}
type dlmmAddLiquidityOneSideArgs struct {
LiquidityParameter dlmmLiquidityOneSideParameter
}
type dlmmAddLiquidityByStrategyOneSideArgs struct {
LiquidityParameter dlmmLiquidityParameterByStrategyOneSide
}
type dlmmCompressedBinDepositAmount struct {
BinID int32
Amount uint32
}
type dlmmAddLiquiditySingleSidePreciseParameter struct {
Bins []dlmmCompressedBinDepositAmount
DecompressMultiplier uint64
}
type dlmmAddLiquiditySingleSidePreciseParameter2 struct {
Bins []dlmmCompressedBinDepositAmount
DecompressMultiplier uint64
MaxAmount uint64
}
type dlmmAddLiquidityOneSidePreciseArgs struct {
Parameter dlmmAddLiquiditySingleSidePreciseParameter
}
type dlmmAddLiquidityOneSidePrecise2Args struct {
LiquidityParameter dlmmAddLiquiditySingleSidePreciseParameter2
RemainingAccountsInfo dlmmRemainingAccountsInfo
}
type dlmmRemoveLiquidityArgs struct { type dlmmRemoveLiquidityArgs struct {
BinLiquidityRemoval []dlmmBinLiquidityReduction BinLiquidityRemoval []dlmmBinLiquidityReduction
} }
@@ -247,6 +311,16 @@ type dlmmLiquidityAccounts struct {
tokenYProgramIdx int tokenYProgramIdx int
} }
type dlmmOneSideLiquidityAccounts struct {
positionIdx int
poolIdx int
userTokenIdx int
reserveIdx int
tokenMintIdx int
userIdx int
tokenProgramIdx 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 {
@@ -276,13 +350,16 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator: case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
return metaoradlmmSwap2Parser(tx, instruction, innerInstructions, offset) return metaoradlmmSwap2Parser(tx, instruction, innerInstructions, offset)
case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator, case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator,
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator: meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator,
meteoraDlmmAddLiquidityByWeightDiscriminator, meteoraDlmmAddLiquidityOneSideDiscriminator,
meteoraDlmmAddLiquidityOneSidePreciseDiscriminator, meteoraDlmmAddLiquidityOneSidePrecise2Discriminator,
meteoraDlmmAddLiquidityByStrategyOneSideDiscriminator:
return metaoradlmmAddLiquidityParser(tx, instruction, innerInstructions, offset) return metaoradlmmAddLiquidityParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmClaimFeeDiscriminator, meteoraDlmmClaimFee2Discriminator: case meteoraDlmmClaimFeeDiscriminator, meteoraDlmmClaimFee2Discriminator:
return metaoradlmmClaimFeeParser(tx, instruction, innerInstructions, offset) return metaoradlmmClaimFeeParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmRebalanceLiquidityDiscriminator: case meteoraDlmmRebalanceLiquidityDiscriminator:
return metaoradlmmRebalanceLiquidityParser(tx, instruction, innerInstructions, offset) return metaoradlmmRebalanceLiquidityParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator, case meteoraDlmmRemoveAllLiquidityDiscriminator, meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator,
meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator: meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator:
return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset) return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmClosePositionDiscriminator, meteoraDlmmClosePosition2Discriminator, meteoraDlmmClosePositionIfEmptyDiscriminator: case meteoraDlmmClosePositionDiscriminator, meteoraDlmmClosePosition2Discriminator, meteoraDlmmClosePositionIfEmptyDiscriminator:
@@ -392,10 +469,13 @@ func metaoradlmmPositionCreateParser(tx *Tx, instruction Instruction, innerInstr
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm create position accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1]) return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm create position accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
} }
createEvent, nextOffset, err := dlmmPositionCreateEventFromInnerInstructions(innerInstructions, instruction, offset) createEvent, nextOffset, found, err := dlmmPositionCreateEventFromInnerInstructions(innerInstructions, instruction, offset)
if err != nil { if err != nil {
return nil, nextOffset, err return nil, nextOffset, err
} }
if !found {
return nil, nextOffset, InstructionIgnoredError
}
offset = nextOffset offset = nextOffset
if !createEvent.LbPair.IsZero() { if !createEvent.LbPair.IsZero() {
@@ -705,9 +785,11 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
amountX uint64 amountX uint64
amountY uint64 amountY uint64
binDist []dlmmBinLiquidityDistribution binDist []dlmmBinLiquidityDistribution
weightDist []dlmmBinLiquidityDistributionByWeight
startBinId int32 startBinId int32
endBinId int32 endBinId int32
hasRange bool hasRange bool
oneSide bool
) )
switch discriminator { switch discriminator {
@@ -751,15 +833,54 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
startBinId = args.LiquidityParameter.StrategyParameters.MinBinId startBinId = args.LiquidityParameter.StrategyParameters.MinBinId
endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId
hasRange = true hasRange = true
case meteoraDlmmAddLiquidityByWeightDiscriminator:
var args dlmmAddLiquidityByWeightArgs
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity by weight decode error: %v, offset, %d, %d", err, offset[0], offset[1])
}
amountX = args.LiquidityParameter.AmountX
amountY = args.LiquidityParameter.AmountY
weightDist = args.LiquidityParameter.BinLiquidityDist
startBinId, endBinId = dlmmMinMaxBinIdFromWeightDistribution(weightDist)
hasRange = len(weightDist) > 0
case meteoraDlmmAddLiquidityOneSideDiscriminator:
var args dlmmAddLiquidityOneSideArgs
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity one side decode error: %v, offset, %d, %d", err, offset[0], offset[1])
}
weightDist = args.LiquidityParameter.BinLiquidityDist
startBinId, endBinId = dlmmMinMaxBinIdFromWeightDistribution(weightDist)
hasRange = len(weightDist) > 0
oneSide = true
case meteoraDlmmAddLiquidityOneSidePreciseDiscriminator:
var args dlmmAddLiquidityOneSidePreciseArgs
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity one side precise decode error: %v, offset, %d, %d", err, offset[0], offset[1])
}
startBinId, endBinId = dlmmMinMaxBinIDFromCompressedDeposits(args.Parameter.Bins)
hasRange = len(args.Parameter.Bins) > 0
oneSide = true
case meteoraDlmmAddLiquidityOneSidePrecise2Discriminator:
var args dlmmAddLiquidityOneSidePrecise2Args
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity one side precise2 decode error: %v, offset, %d, %d", err, offset[0], offset[1])
}
startBinId, endBinId = dlmmMinMaxBinIDFromCompressedDeposits(args.LiquidityParameter.Bins)
hasRange = len(args.LiquidityParameter.Bins) > 0
oneSide = true
case meteoraDlmmAddLiquidityByStrategyOneSideDiscriminator:
var args dlmmAddLiquidityByStrategyOneSideArgs
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm add liquidity by strategy one side decode error: %v, offset, %d, %d", err, offset[0], offset[1])
}
startBinId = args.LiquidityParameter.StrategyParameters.MinBinId
endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId
hasRange = true
oneSide = true
default: default:
return nil, increaseOffset(offset), InstructionIgnoredError 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) addEvent, nextOffset, err := dlmmAddLiquidityEventFromInnerInstructions(innerInstructions, instruction, offset)
if err != nil { if err != nil {
return nil, nextOffset, err return nil, nextOffset, err
@@ -768,9 +889,25 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
amountX = addEvent.Amounts[0] amountX = addEvent.Amounts[0]
amountY = addEvent.Amounts[1] amountY = addEvent.Amounts[1]
if oneSide {
swaps, err := dlmmBuildOneSideAddSwap(tx, instruction, addEvent, weightDist, startBinId, endBinId, hasRange, entryContract)
if err != nil {
return nil, offset, err
}
return swaps, offset, nil
}
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])
}
binChanges := []DlmmBinLiquidityChange(nil) binChanges := []DlmmBinLiquidityChange(nil)
if len(binDist) > 0 { if len(binDist) > 0 {
binChanges = dlmmBinChangesFromDistribution(amountX, amountY, binDist) binChanges = dlmmBinChangesFromDistribution(amountX, amountY, binDist)
} else if len(weightDist) > 0 {
// Weight-only params do not preserve per-side amounts for each bin, so keep the affected range only.
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
} else if hasRange { } else if hasRange {
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0) binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
} }
@@ -901,6 +1038,8 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
) )
switch discriminator { switch discriminator {
case meteoraDlmmRemoveAllLiquidityDiscriminator:
removeBp = 10000
case meteoraDlmmRemoveLiquidityDiscriminator: case meteoraDlmmRemoveLiquidityDiscriminator:
var args dlmmRemoveLiquidityArgs var args dlmmRemoveLiquidityArgs
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil { if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
@@ -1446,11 +1585,11 @@ func dlmmRebalancingEventFromInnerInstructions(innerInstructions InnerInstructio
return dlmmRebalancingEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm rebalance liquidity event not found, offset, %d, %d", offset[0], prefixLen) return dlmmRebalancingEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm rebalance liquidity event not found, offset, %d, %d", offset[0], prefixLen)
} }
func dlmmPositionCreateEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmPositionCreateEvent, [2]uint, error) { func dlmmPositionCreateEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmPositionCreateEvent, [2]uint, bool, error) {
var prefixLen = offset[1] var prefixLen = offset[1]
inners, err := getInnerInstructions(innerInstructions, prefixLen) inners, err := getInnerInstructions(innerInstructions, prefixLen)
if err != nil { if err != nil {
return dlmmPositionCreateEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm create position get inner instructions error: %v, offset, %d, %d", err, offset[0], prefixLen) return dlmmPositionCreateEvent{}, increaseOffset(offset), false, fmt.Errorf("meteora dlmm create position get inner instructions error: %v, offset, %d, %d", err, offset[0], prefixLen)
} }
for innerIndex, innerInstr := range inners { for innerIndex, innerInstr := range inners {
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex { if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
@@ -1465,9 +1604,9 @@ func dlmmPositionCreateEventFromInnerInstructions(innerInstructions InnerInstruc
} else { } else {
offset[1] = uint(innerIndex) + 1 + prefixLen offset[1] = uint(innerIndex) + 1 + prefixLen
} }
return event, offset, nil return event, offset, true, nil
} }
return dlmmPositionCreateEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm create position event not found, offset, %d, %d", offset[0], prefixLen) return dlmmPositionCreateEvent{}, increaseOffset(offset), false, nil
} }
func dlmmPositionCloseEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmPositionCloseEvent, [2]uint, bool, error) { func dlmmPositionCloseEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmPositionCloseEvent, [2]uint, bool, error) {
@@ -1787,6 +1926,164 @@ func resolveDlmmLiquidityAccounts(result *RawTx, accounts []int) (dlmmLiquidityA
}, nil }, nil
} }
func resolveDlmmOneSideLiquidityAccounts(result *RawTx, accounts []int) (dlmmOneSideLiquidityAccounts, error) {
if len(accounts) < 10 {
return dlmmOneSideLiquidityAccounts{}, fmt.Errorf("accounts too short, expected at least 10")
}
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 dlmmOneSideLiquidityAccounts{}, fmt.Errorf("event authority not found")
}
if eventAuthorityPos+1 >= len(accounts) || !accountList[accounts[eventAuthorityPos+1]].Equals(meteoraDlmmProgram) {
return dlmmOneSideLiquidityAccounts{}, fmt.Errorf("program id not found after event authority")
}
tokenProgramPos := eventAuthorityPos - 1
userPos := eventAuthorityPos - 2
if tokenProgramPos < 0 || userPos < 0 {
return dlmmOneSideLiquidityAccounts{}, fmt.Errorf("one side liquidity account positions invalid")
}
if len(accounts) < 6 {
return dlmmOneSideLiquidityAccounts{}, fmt.Errorf("accounts too short for one side liquidity parsing")
}
return dlmmOneSideLiquidityAccounts{
positionIdx: accounts[0],
poolIdx: accounts[1],
userTokenIdx: accounts[3],
reserveIdx: accounts[4],
tokenMintIdx: accounts[5],
userIdx: accounts[userPos],
tokenProgramIdx: accounts[tokenProgramPos],
}, nil
}
func dlmmBuildOneSideAddSwap(
tx *Tx,
instruction Instruction,
addEvent dlmmAddLiquidityEvent,
weightDist []dlmmBinLiquidityDistributionByWeight,
startBinId int32,
endBinId int32,
hasRange bool,
entryContract solana.PublicKey,
) ([]Swap, error) {
result := tx.rawTx
accounts, err := resolveDlmmOneSideLiquidityAccounts(result, instruction.Accounts)
if err != nil {
return nil, err
}
knownMint := result.accountList[accounts.tokenMintIdx]
knownTokenProgram := result.accountList[accounts.tokenProgramIdx]
knownDecimals, ok := dlmmTokenDecimals(result, accounts.reserveIdx)
if !ok {
knownDecimals, _ = dlmmTokenDecimals(result, accounts.userTokenIdx)
}
knownReserveBalance := getAccountBalanceAfterTx(result, accounts.reserveIdx)
knownUserBalance := getAccountBalanceAfterTx(result, accounts.userTokenIdx)
if knownMint.Equals(wSolMint) {
if solAmount, err := GetSolAfterTx(result, accounts.userIdx); err == nil {
knownUserBalance = knownUserBalance.Add(decimal.NewFromUint64(solAmount))
}
}
binChanges := []DlmmBinLiquidityChange(nil)
if len(weightDist) > 0 {
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
} else if hasRange {
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
}
eventUser := result.accountList[accounts.userIdx]
if !addEvent.From.IsZero() {
eventUser = addEvent.From
}
positionAccount := result.accountList[accounts.positionIdx]
if !addEvent.Position.IsZero() {
positionAccount = addEvent.Position
}
swap := Swap{
Program: SolProgramMeteoraDLMM,
Event: "add",
Pool: result.accountList[accounts.poolIdx],
User: eventUser,
EntryContract: entryContract,
ActiveBinId: addEvent.ActiveBinId,
StartBinId: startBinId,
EndBinId: endBinId,
BinChanges: binChanges,
PositionAccount: positionAccount,
}
knownIsX := dlmmInferOneSideLiquidityAxis(result, accounts, addEvent)
if knownIsX {
swap.BaseMint = knownMint
swap.BaseTokenProgram = knownTokenProgram
swap.BaseMintDecimals = knownDecimals
swap.BaseAmount = decimal.NewFromUint64(addEvent.Amounts[0])
swap.BaseReserve = knownReserveBalance
swap.UserBaseBalance = knownUserBalance
if _, exists := tx.Token[knownMint]; !exists && !knownMint.Equals(wSolMint) {
tx.Token[knownMint] = TokenMeta{
Mint: knownMint,
Decimals: knownDecimals,
TokenProgram: knownTokenProgram,
}
}
} else {
swap.QuoteMint = knownMint
swap.QuoteTokenProgram = knownTokenProgram
swap.QuoteMintDecimals = knownDecimals
swap.QuoteAmount = decimal.NewFromUint64(addEvent.Amounts[1])
swap.QuoteReserve = knownReserveBalance
swap.UserQuoteBalance = knownUserBalance
if _, exists := tx.Token[knownMint]; !exists && !knownMint.Equals(wSolMint) {
tx.Token[knownMint] = TokenMeta{
Mint: knownMint,
Decimals: knownDecimals,
TokenProgram: knownTokenProgram,
}
}
}
return []Swap{swap}, nil
}
func dlmmInferOneSideLiquidityAxis(result *RawTx, accounts dlmmOneSideLiquidityAccounts, addEvent dlmmAddLiquidityEvent) bool {
knownAmount, ok := dlmmTokenDelta(result, accounts.reserveIdx)
if !ok || knownAmount.IsZero() {
knownAmount, _ = dlmmTokenDelta(result, accounts.userTokenIdx)
}
amountX := decimal.NewFromUint64(addEvent.Amounts[0])
amountY := decimal.NewFromUint64(addEvent.Amounts[1])
switch {
case !knownAmount.IsZero() && knownAmount.Equal(amountX) && !knownAmount.Equal(amountY):
return true
case !knownAmount.IsZero() && knownAmount.Equal(amountY) && !knownAmount.Equal(amountX):
return false
case addEvent.Amounts[0] > 0 && addEvent.Amounts[1] == 0:
return true
case addEvent.Amounts[1] > 0 && addEvent.Amounts[0] == 0:
return false
default:
return true
}
}
func resolveDlmmClaimFeeAccounts(result *RawTx, data []byte, accounts []int) (dlmmLiquidityAccounts, error) { func resolveDlmmClaimFeeAccounts(result *RawTx, data []byte, accounts []int) (dlmmLiquidityAccounts, error) {
if len(data) < 8 { if len(data) < 8 {
return dlmmLiquidityAccounts{}, fmt.Errorf("instruction data too short") return dlmmLiquidityAccounts{}, fmt.Errorf("instruction data too short")
@@ -2010,6 +2307,23 @@ func dlmmBinChangesFromRange(startBinId, endBinId int32, bpsToRemove uint16) []D
return changes return changes
} }
func dlmmMinMaxBinIDFromCompressedDeposits(bins []dlmmCompressedBinDepositAmount) (startBinID, endBinID int32) {
if len(bins) == 0 {
return 0, 0
}
startBinID = bins[0].BinID
endBinID = bins[0].BinID
for _, bin := range bins[1:] {
if bin.BinID < startBinID {
startBinID = bin.BinID
}
if bin.BinID > endBinID {
endBinID = bin.BinID
}
}
return startBinID, endBinID
}
func dlmmCommonRemoveBp(reduction []dlmmBinLiquidityReduction) int32 { func dlmmCommonRemoveBp(reduction []dlmmBinLiquidityReduction) int32 {
if len(reduction) == 0 { if len(reduction) == 0 {
return 0 return 0
@@ -2047,6 +2361,23 @@ func dlmmMinMaxBinIdFromDistribution(dist []dlmmBinLiquidityDistribution) (int32
return min, max return min, max
} }
func dlmmMinMaxBinIdFromWeightDistribution(dist []dlmmBinLiquidityDistributionByWeight) (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) { func dlmmMinMaxBinIdFromReduction(reduction []dlmmBinLiquidityReduction) (int32, int32) {
if len(reduction) == 0 { if len(reduction) == 0 {
return 0, 0 return 0, 0

View File

@@ -872,7 +872,9 @@ func ConvertYellowstoneGrpcTransactionToSolanaTransaction(y *pb.SubscribeUpdateT
} }
sTx.Meta.Fee = meta.Fee sTx.Meta.Fee = meta.Fee
//sTx.Meta.InnerInstructions = meta.InnerInstructions //sTx.Meta.InnerInstructions = meta.InnerInstructions
sTx.Meta.ComputeUnitsConsumed = *meta.ComputeUnitsConsumed if meta.ComputeUnitsConsumed != nil {
sTx.Meta.ComputeUnitsConsumed = *meta.ComputeUnitsConsumed
}
for _, innerInstr := range meta.InnerInstructions { for _, innerInstr := range meta.InnerInstructions {
var instrs []Instruction var instrs []Instruction
for _, instr := range innerInstr.Instructions { for _, instr := range innerInstr.Instructions {