From 5da088ce131e4c06f5a3ef318b766bc5ae33cfc6 Mon Sep 17 00:00:00 2001 From: thloyi Date: Mon, 2 Feb 2026 17:59:47 +0800 Subject: [PATCH] metaora dlmm init --- meta.go | 20 ++++++------ metaoradlmm.go | 53 +++++++++++++++++++++++++++++++ pump_test.go | 6 ++++ rawtx.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 152 insertions(+), 12 deletions(-) diff --git a/meta.go b/meta.go index 932a866..22a4547 100644 --- a/meta.go +++ b/meta.go @@ -67,15 +67,17 @@ var ( ) var ( - 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") - meteoraDlmmSwapEventDiscriminator = calculateDiscriminator("event:Swap") - meteoraDlmmAddLiquidityDiscriminator = calculateDiscriminator("global:add_liquidity") - meteoraDlmmAddLiquidity2Discriminator = calculateDiscriminator("global:add_liquidity2") + 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") + 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") diff --git a/metaoradlmm.go b/metaoradlmm.go index dd1e5fe..9104dda 100644 --- a/metaoradlmm.go +++ b/metaoradlmm.go @@ -199,6 +199,8 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI discriminator := *(*[8]byte)(decode[:8]) switch discriminator { + case meteoraInitializeLbPairDiscriminator: + return metaoradlmmInitializeParser(tx, instruction, innerInstructions, offset) case meteoraDlmmSwapDiscriminator, meteoraDlmmSwapExactOutDiscriminator, meteoraDlmmSwapWithPriceImpactDiscriminator: return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset) case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator: @@ -214,6 +216,57 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI } } +func metaoradlmmInitializeParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { + market := tx.rawTx.accountList[instruction.Accounts[0]] + token0 := tx.rawTx.accountList[instruction.Accounts[2]] + token1 := tx.rawTx.accountList[instruction.Accounts[3]] + + entryContract := tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex] + + var baseDecimals uint8 + var quoteDecimals uint8 + for _, acc := range tx.rawTx.Meta.PostTokenBalances { + if acc.MintAccount.Equals(token0) { + baseDecimals = uint8(acc.UITokenAmount.Decimals) + } + if acc.MintAccount.Equals(token1) { + quoteDecimals = uint8(acc.UITokenAmount.Decimals) + } + } + swap := Swap{ + Program: SolProgramMeteoraDLMM, + Event: "create", + Pool: market, + BaseMint: token0, + QuoteMint: token1, + BaseTokenProgram: tx.rawTx.accountList[instruction.Accounts[11]], + QuoteTokenProgram: tx.rawTx.accountList[instruction.Accounts[12]], + Creator: tx.rawTx.accountList[0], + BaseMintDecimals: baseDecimals, + QuoteMintDecimals: quoteDecimals, + User: tx.rawTx.accountList[instruction.Accounts[8]], + EntryContract: entryContract, + } + var prefixLen = offset[1] + inners, err := getInnerInstructions(innerInstructions, prefixLen) + if err != nil { + return nil, increaseOffset(offset), fmt.Errorf("pump create get inner instructions error: %v, offset, %d, %d", err, offset[0], offset[1]) + } + var programIndex = instruction.ProgramIDIndex + + for innerIndex, innerInstr := range inners { + if innerInstr.ProgramIDIndex == programIndex && bytes.Equal(innerInstr.Data[:8], pumpEventDiscriminator[:]) && bytes.Equal(innerInstr.Data[8:16], meteoraInitializeLbPairEventDiscriminator[:]) { + if offset[1] == 0 { + offset[0] += 1 + } else { + offset[1] += uint(innerIndex) + 1 + prefixLen + } + break + } + } + return []Swap{swap}, offset, nil +} + func metaoradlmmSwapParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) { result := tx.rawTx diff --git a/pump_test.go b/pump_test.go index fb06892..0b5f261 100644 --- a/pump_test.go +++ b/pump_test.go @@ -29,3 +29,9 @@ func TestTradeEvent(t *testing.T) { fmt.Println(len(xx), err) } +func TestCal(t *testing.T) { + //e445a52e51cb9a1db94afc7d1bd7bc6f5e99e54b + // . b94afc7d1bd7bc6f + s := calculateDiscriminator("event:LbPairCreate") + fmt.Println(hex.EncodeToString(s[:])) +} diff --git a/rawtx.go b/rawtx.go index f73ff3c..9bd0bcf 100644 --- a/rawtx.go +++ b/rawtx.go @@ -513,6 +513,78 @@ func intSliceFromUint16Slice(in []uint16) []int { } return out } +func getAtaIdxByOwner(result *RawTx, owner solana.PublicKey, mint solana.PublicKey) (int, error) { + var preBalance *TokenBalance + for _, pre := range result.Meta.PreTokenBalances { + if pre.MintAccount == mint && pre.OwnerAccount != nil && pre.OwnerAccount.Equals(owner) { + preBalance = &pre + break + } + } + var postBalance *TokenBalance + + for _, post := range result.Meta.PostTokenBalances { + if post.MintAccount == mint && post.OwnerAccount != nil && post.OwnerAccount.Equals(owner) { + // post.ParseAccount() + postBalance = &post + break + } + } + if preBalance == nil && postBalance == nil { + return 0, fmt.Errorf("account not found") + } + if preBalance != nil && postBalance != nil && preBalance.AccountIndex != postBalance.AccountIndex { + return 0, fmt.Errorf("ata index not match") + } + if postBalance == nil { + return preBalance.AccountIndex, nil + } + return postBalance.AccountIndex, nil +} + +func getAtaByOwner(result *RawTx, owner solana.PublicKey, mint solana.PublicKey) (*TokenBalance, error) { + var preBalance *TokenBalance + for _, pre := range result.Meta.PreTokenBalances { + if pre.MintAccount == mint && pre.OwnerAccount != nil && pre.OwnerAccount.Equals(owner) { + preBalance = &pre + break + } + } + var postBalance *TokenBalance + + for _, post := range result.Meta.PostTokenBalances { + if post.MintAccount == mint && post.OwnerAccount != nil && post.OwnerAccount.Equals(owner) { + // post.ParseAccount() + postBalance = &post + break + } + } + if preBalance == nil && postBalance == nil { + return nil, fmt.Errorf("account not found") + } + if preBalance != nil && postBalance != nil && preBalance.AccountIndex != postBalance.AccountIndex { + return nil, fmt.Errorf("ata index not match") + } + if postBalance == nil { + preBalance.ParseAccount() + return &TokenBalance{ + AccountIndex: preBalance.AccountIndex, + MintAccount: preBalance.MintAccount, + OwnerAccount: preBalance.OwnerAccount, + ProgramIDAccount: preBalance.ProgramIDAccount, + Mint: preBalance.Mint, + Owner: preBalance.Owner, + ProgramID: preBalance.ProgramID, + UITokenAmount: UITokenAmount{ + Amount: "0", + Decimals: preBalance.UITokenAmount.Decimals, + UIAmount: 0, + UIAmountString: "0", + }, + }, nil + } + return postBalance, nil +} func getTokenBalanceAfterTx(result *RawTx, accountIndex int) (*TokenBalance, error) { var preBalance *TokenBalance @@ -581,8 +653,12 @@ func tokenBalanceChange(result *RawTx, accountIndex int, tokenProgram, mint sola break } } + var err error if ataIndex == 0 { - return decimal.Zero, ataIndex + ataIndex, err = getAtaIdxByOwner(result, result.accountList[accountIndex], mint) + if err != nil { + return decimal.Zero, ataIndex + } } before := decimal.Zero after := decimal.Zero @@ -625,10 +701,13 @@ func GetTokenBalanceAfterTx(result *RawTx, accountIndex int, tokenProgram, mint break } } + var x *TokenBalance + var err error if ataIndex == 0 { - return decimal.Zero + x, err = getAtaByOwner(result, result.accountList[accountIndex], mint) + } else { + x, err = getTokenBalanceAfterTx(result, ataIndex) } - x, err := getTokenBalanceAfterTx(result, ataIndex) if err != nil { return decimal.Zero }