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 (
meteoraInitializeLbPairDiscriminator = calculateDiscriminator("global:initialize_lb_pair2")
meteoraInitializeLbPairEventDiscriminator = calculateDiscriminator("event:LbPairCreate")
meteoraDlmmSwapDiscriminator = calculateDiscriminator("global:swap")
meteoraDlmmSwap2Discriminator = calculateDiscriminator("global:swap2")
meteoraDlmmSwapExactOutDiscriminator = calculateDiscriminator("global:swap_exact_out")
meteoraDlmmSwapExactOut2Discriminator = calculateDiscriminator("global:swap_exact_out2")
meteoraDlmmSwapWithPriceImpactDiscriminator = calculateDiscriminator("global:swap_with_price_impact")
meteoraDlmmSwapWithPriceImpact2Discriminator = calculateDiscriminator("global:swap_with_price_impact2")
meteoraDlmmInitializePositionDiscriminator = calculateDiscriminator("global:initialize_position")
meteoraDlmmInitializePosition2Discriminator = calculateDiscriminator("global:initialize_position2")
meteoraDlmmInitializePositionByOperatorDiscriminator = calculateDiscriminator("global:initialize_position_by_operator")
meteoraDlmmInitializePositionPdaDiscriminator = calculateDiscriminator("global:initialize_position_pda")
meteoraDlmmClosePositionDiscriminator = calculateDiscriminator("global:close_position")
meteoraDlmmClosePosition2Discriminator = calculateDiscriminator("global:close_position2")
meteoraDlmmClosePositionIfEmptyDiscriminator = calculateDiscriminator("global:close_position_if_empty")
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")
meteoraDlmmClaimFeeDiscriminator = calculateDiscriminator("global:claim_fee")
meteoraDlmmClaimFee2Discriminator = calculateDiscriminator("global:claim_fee2")
meteoraDlmmRebalanceLiquidityDiscriminator = calculateDiscriminator("global:rebalance_liquidity")
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")
meteoraDlmmClaimFeeEventDiscriminator = calculateDiscriminator("event:ClaimFee")
meteoraDlmmClaimFee2EventDiscriminator = calculateDiscriminator("event:ClaimFee2")
meteoraDlmmPositionCloseEventDiscriminator = calculateDiscriminator("event:PositionClose")
meteoraDlmmPositionCreateEventDiscriminator = calculateDiscriminator("event:PositionCreate")
meteoraDlmmRebalancingEventDiscriminator = calculateDiscriminator("event:Rebalancing")
meteoraDlmmRemoveLiquidityEventDiscriminator = calculateDiscriminator("event:RemoveLiquidity")
meteoraInitializeLbPairDiscriminator = calculateDiscriminator("global:initialize_lb_pair2")
meteoraInitializeLbPairEventDiscriminator = calculateDiscriminator("event:LbPairCreate")
meteoraDlmmSwapDiscriminator = calculateDiscriminator("global:swap")
meteoraDlmmSwap2Discriminator = calculateDiscriminator("global:swap2")
meteoraDlmmSwapExactOutDiscriminator = calculateDiscriminator("global:swap_exact_out")
meteoraDlmmSwapExactOut2Discriminator = calculateDiscriminator("global:swap_exact_out2")
meteoraDlmmSwapWithPriceImpactDiscriminator = calculateDiscriminator("global:swap_with_price_impact")
meteoraDlmmSwapWithPriceImpact2Discriminator = calculateDiscriminator("global:swap_with_price_impact2")
meteoraDlmmInitializePositionDiscriminator = calculateDiscriminator("global:initialize_position")
meteoraDlmmInitializePosition2Discriminator = calculateDiscriminator("global:initialize_position2")
meteoraDlmmInitializePositionByOperatorDiscriminator = calculateDiscriminator("global:initialize_position_by_operator")
meteoraDlmmInitializePositionPdaDiscriminator = calculateDiscriminator("global:initialize_position_pda")
meteoraDlmmClosePositionDiscriminator = calculateDiscriminator("global:close_position")
meteoraDlmmClosePosition2Discriminator = calculateDiscriminator("global:close_position2")
meteoraDlmmClosePositionIfEmptyDiscriminator = calculateDiscriminator("global:close_position_if_empty")
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")
meteoraDlmmAddLiquidityByWeightDiscriminator = calculateDiscriminator("global:add_liquidity_by_weight")
meteoraDlmmAddLiquidityOneSideDiscriminator = calculateDiscriminator("global:add_liquidity_one_side")
meteoraDlmmAddLiquidityOneSidePreciseDiscriminator = calculateDiscriminator("global:add_liquidity_one_side_precise")
meteoraDlmmAddLiquidityOneSidePrecise2Discriminator = calculateDiscriminator("global:add_liquidity_one_side_precise2")
meteoraDlmmAddLiquidityByStrategyOneSideDiscriminator = calculateDiscriminator("global:add_liquidity_by_strategy_one_side")
meteoraDlmmClaimFeeDiscriminator = calculateDiscriminator("global:claim_fee")
meteoraDlmmClaimFee2Discriminator = calculateDiscriminator("global:claim_fee2")
meteoraDlmmRebalanceLiquidityDiscriminator = calculateDiscriminator("global:rebalance_liquidity")
meteoraDlmmRemoveAllLiquidityDiscriminator = calculateDiscriminator("global:remove_all_liquidity")
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")
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 (

View File

@@ -117,6 +117,11 @@ type dlmmBinLiquidityDistribution struct {
DistributionY uint16
}
type dlmmBinLiquidityDistributionByWeight struct {
BinId int32
Weight uint16
}
type dlmmBinLiquidityReduction struct {
BinId int32
BpsToRemove uint16
@@ -143,6 +148,14 @@ type dlmmLiquidityParameterByStrategy struct {
StrategyParameters dlmmStrategyParameters
}
type dlmmLiquidityParameterByWeight struct {
AmountX uint64
AmountY uint64
ActiveID int32
MaxActiveBinSlippage int32
BinLiquidityDist []dlmmBinLiquidityDistributionByWeight
}
type dlmmAddLiquidityArgs struct {
LiquidityParameter dlmmLiquidityParameter
}
@@ -161,6 +174,57 @@ type dlmmAddLiquidityByStrategy2Args struct {
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 {
BinLiquidityRemoval []dlmmBinLiquidityReduction
}
@@ -247,6 +311,16 @@ type dlmmLiquidityAccounts struct {
tokenYProgramIdx int
}
type dlmmOneSideLiquidityAccounts struct {
positionIdx int
poolIdx int
userTokenIdx int
reserveIdx int
tokenMintIdx int
userIdx int
tokenProgramIdx int
}
var meteoraDlmmEventAuthority = func() solana.PublicKey {
key, _, err := solana.FindProgramAddress([][]byte{[]byte("__event_authority")}, meteoraDlmmProgram)
if err != nil {
@@ -276,13 +350,16 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
return metaoradlmmSwap2Parser(tx, instruction, innerInstructions, offset)
case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator,
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator:
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator,
meteoraDlmmAddLiquidityByWeightDiscriminator, meteoraDlmmAddLiquidityOneSideDiscriminator,
meteoraDlmmAddLiquidityOneSidePreciseDiscriminator, meteoraDlmmAddLiquidityOneSidePrecise2Discriminator,
meteoraDlmmAddLiquidityByStrategyOneSideDiscriminator:
return metaoradlmmAddLiquidityParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmClaimFeeDiscriminator, meteoraDlmmClaimFee2Discriminator:
return metaoradlmmClaimFeeParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmRebalanceLiquidityDiscriminator:
return metaoradlmmRebalanceLiquidityParser(tx, instruction, innerInstructions, offset)
case meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator,
case meteoraDlmmRemoveAllLiquidityDiscriminator, meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator,
meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator:
return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset)
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])
}
createEvent, nextOffset, err := dlmmPositionCreateEventFromInnerInstructions(innerInstructions, instruction, offset)
createEvent, nextOffset, found, err := dlmmPositionCreateEventFromInnerInstructions(innerInstructions, instruction, offset)
if err != nil {
return nil, nextOffset, err
}
if !found {
return nil, nextOffset, InstructionIgnoredError
}
offset = nextOffset
if !createEvent.LbPair.IsZero() {
@@ -705,9 +785,11 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
amountX uint64
amountY uint64
binDist []dlmmBinLiquidityDistribution
weightDist []dlmmBinLiquidityDistributionByWeight
startBinId int32
endBinId int32
hasRange bool
oneSide bool
)
switch discriminator {
@@ -751,15 +833,54 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
startBinId = args.LiquidityParameter.StrategyParameters.MinBinId
endBinId = args.LiquidityParameter.StrategyParameters.MaxBinId
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:
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
@@ -768,9 +889,25 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
amountX = addEvent.Amounts[0]
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)
if len(binDist) > 0 {
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 {
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, 0)
}
@@ -901,6 +1038,8 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
)
switch discriminator {
case meteoraDlmmRemoveAllLiquidityDiscriminator:
removeBp = 10000
case meteoraDlmmRemoveLiquidityDiscriminator:
var args dlmmRemoveLiquidityArgs
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)
}
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]
inners, err := getInnerInstructions(innerInstructions, prefixLen)
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 {
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
@@ -1465,9 +1604,9 @@ func dlmmPositionCreateEventFromInnerInstructions(innerInstructions InnerInstruc
} else {
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) {
@@ -1787,6 +1926,164 @@ func resolveDlmmLiquidityAccounts(result *RawTx, accounts []int) (dlmmLiquidityA
}, 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) {
if len(data) < 8 {
return dlmmLiquidityAccounts{}, fmt.Errorf("instruction data too short")
@@ -2010,6 +2307,23 @@ func dlmmBinChangesFromRange(startBinId, endBinId int32, bpsToRemove uint16) []D
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 {
if len(reduction) == 0 {
return 0
@@ -2047,6 +2361,23 @@ func dlmmMinMaxBinIdFromDistribution(dist []dlmmBinLiquidityDistribution) (int32
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) {
if len(reduction) == 0 {
return 0, 0

View File

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