Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03030d817d | ||
|
|
401dca225a | ||
|
|
db8c8727f4 | ||
|
|
09de6ba649 | ||
|
|
7a82990770 | ||
|
|
e82bcb3c07 | ||
|
|
a74f769064 |
54
consts.go
54
consts.go
@@ -185,6 +185,7 @@ var mevAgentFeeAddresses = map[solana.PublicKey]string{
|
|||||||
solana.MustPublicKeyFromBase58("soyascXFW5wEEYiwfEmHy2pNwomqzvggJosGVD6TJdY"): MevAgentSoyas,
|
solana.MustPublicKeyFromBase58("soyascXFW5wEEYiwfEmHy2pNwomqzvggJosGVD6TJdY"): MevAgentSoyas,
|
||||||
solana.MustPublicKeyFromBase58("soyasDBdKjADwPz3xk82U3TNPRDKEWJj7wWLajNHZ1L"): MevAgentSoyas,
|
solana.MustPublicKeyFromBase58("soyasDBdKjADwPz3xk82U3TNPRDKEWJj7wWLajNHZ1L"): MevAgentSoyas,
|
||||||
solana.MustPublicKeyFromBase58("soyasE2abjBAynmHbGWgEwk4ctBy7JMTUCNrMbjcnyH"): MevAgentSoyas,
|
solana.MustPublicKeyFromBase58("soyasE2abjBAynmHbGWgEwk4ctBy7JMTUCNrMbjcnyH"): MevAgentSoyas,
|
||||||
|
solana.MustPublicKeyFromBase58("soyasF3QPWPAKKmgA3GjfWax1kmTT1aoqSGxPzVLNUQ"): MevAgentSoyas,
|
||||||
solana.MustPublicKeyFromBase58("ste11JV3MLMM7x7EJUM2sXcJC1H7F4jBLnP9a9PG8PH"): MevAgentStellium,
|
solana.MustPublicKeyFromBase58("ste11JV3MLMM7x7EJUM2sXcJC1H7F4jBLnP9a9PG8PH"): MevAgentStellium,
|
||||||
solana.MustPublicKeyFromBase58("ste11MWPjXCRfQryCshzi86SGhuXjF4Lv6xMXD2AoSt"): MevAgentStellium,
|
solana.MustPublicKeyFromBase58("ste11MWPjXCRfQryCshzi86SGhuXjF4Lv6xMXD2AoSt"): MevAgentStellium,
|
||||||
solana.MustPublicKeyFromBase58("ste11p5x8tJ53H1NbNQsRBg1YNRd4GcVpxtDw8PBpmb"): MevAgentStellium,
|
solana.MustPublicKeyFromBase58("ste11p5x8tJ53H1NbNQsRBg1YNRd4GcVpxtDw8PBpmb"): MevAgentStellium,
|
||||||
@@ -209,6 +210,14 @@ var mevAgentFeeAddresses = map[solana.PublicKey]string{
|
|||||||
solana.MustPublicKeyFromBase58("B1ooMauwuJPhHsXqt3uj7B92CAFG8kaD1Q2iGEmGYnx"): MevAgentAstralane,
|
solana.MustPublicKeyFromBase58("B1ooMauwuJPhHsXqt3uj7B92CAFG8kaD1Q2iGEmGYnx"): MevAgentAstralane,
|
||||||
solana.MustPublicKeyFromBase58("B1ooMdjcY7zemxDWiH8jVZPxEMdHnE5AraWPHdHQoPj"): MevAgentAstralane,
|
solana.MustPublicKeyFromBase58("B1ooMdjcY7zemxDWiH8jVZPxEMdHnE5AraWPHdHQoPj"): MevAgentAstralane,
|
||||||
solana.MustPublicKeyFromBase58("B1ooMKzu6siJzQutP6a6oLiY3fpzgQnBZsAjxuAm9qo"): MevAgentAstralane,
|
solana.MustPublicKeyFromBase58("B1ooMKzu6siJzQutP6a6oLiY3fpzgQnBZsAjxuAm9qo"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AstrA1ejL4UeXC2SBP4cpeEmtcFPZVLxx3XGKXyCW6to"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AsTra79FET4aCKWspPqeSFvjJNyp96SvAnrmyAxqg5b7"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AsTRADtvb6tTmrsqULQ9Wji9PigDMjhfEMza6zkynEvV"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AsTRAEoyMofR3vUPpf9k68Gsfb6ymTZttEtsAbv8Bk4d"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AStrAJv2RN2hKCHxwUMtqmSxgdcNZbihCwc1mCSnG83W"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("Astran35aiQUF57XZsmkWMtNCtXGLzs8upfiqXxth2bz"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("AStRAnpi6kFrKypragExgeRoJ1QnKH7pbSjLAKQVWUum"): MevAgentAstralane,
|
||||||
|
solana.MustPublicKeyFromBase58("ASTRaoF93eYt73TYvwtsv6fMWHWbGmMUZfVZPo3CRU9C"): MevAgentAstralane,
|
||||||
solana.MustPublicKeyFromBase58("Gu2UGEfze3Gg5cHuEC4jGbyCufgpev75RkVvBdKKtf12"): MevAgentNozomi,
|
solana.MustPublicKeyFromBase58("Gu2UGEfze3Gg5cHuEC4jGbyCufgpev75RkVvBdKKtf12"): MevAgentNozomi,
|
||||||
solana.MustPublicKeyFromBase58("E8wD3SMD1trozPrvSN9F6SyuUXD7rrFDuR3WexGziKG5"): MevAgent0slot,
|
solana.MustPublicKeyFromBase58("E8wD3SMD1trozPrvSN9F6SyuUXD7rrFDuR3WexGziKG5"): MevAgent0slot,
|
||||||
solana.MustPublicKeyFromBase58("18hCV7f9CPmZRAH3QCNZaGHhHeNSfisQKeKuFkQsPLY"): MevAgent0slot,
|
solana.MustPublicKeyFromBase58("18hCV7f9CPmZRAH3QCNZaGHhHeNSfisQKeKuFkQsPLY"): MevAgent0slot,
|
||||||
@@ -327,6 +336,51 @@ var mevAgentFeeAddresses = map[solana.PublicKey]string{
|
|||||||
solana.MustPublicKeyFromBase58("bgH7YhymSykyvMa3nAZpzvrn73owJHU5iB75S1aiLT9"): MevAgentNozomi,
|
solana.MustPublicKeyFromBase58("bgH7YhymSykyvMa3nAZpzvrn73owJHU5iB75S1aiLT9"): MevAgentNozomi,
|
||||||
solana.MustPublicKeyFromBase58("pfngGVVQLiVRFbLWw3Ektiv17ef9NiRZbcgdAhh4ZEW"): MevAgentNozomi,
|
solana.MustPublicKeyFromBase58("pfngGVVQLiVRFbLWw3Ektiv17ef9NiRZbcgdAhh4ZEW"): MevAgentNozomi,
|
||||||
solana.MustPublicKeyFromBase58("nEFs3jph8HJt7honu3k7XtGUufMnwAvSXmXcKSPxryP"): MevAgentNozomi,
|
solana.MustPublicKeyFromBase58("nEFs3jph8HJt7honu3k7XtGUufMnwAvSXmXcKSPxryP"): MevAgentNozomi,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con11xLjPddfzRwRUB16sbFZggp2JeJkCeWREyR8X"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con11TM1RuAQzbQzYjTy4Ekfap9Lnc9fnEbQYEd6Q"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con113Bvi76nS5AzUiRDC2fqjfzkNMUNRLgQybMYt"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con1QGHJK232s8yZpzZZwqPexnAKcoyKj626LNsMv"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con1zUzb6qJVFz5tNkPq1Ahm8H1qKW7Q48252QbkQ"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con16d3MSwd3SAiwvr2LwgkpE7ot8zntbpuec8HAx"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con1i7mpa7Qc6epYJ6r4P9AbU77DFFz173r59Df1x"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con18nWn8TdAGL7JX8PertfMUGVSc899NawokJ4Bq"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con1GKusK2EqsfzrDzGPaYZSxQtFGzJiRMMU9Zm2g"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Fa1con1RDwVwM9VrJ53CwVefD3VU9c58EMpDawV7fLMi"): MevagentFa1con,
|
||||||
|
solana.MustPublicKeyFromBase58("Sp1x2AqpQckPLaWnWCJUNg8k6qQexfaEWcSRKf5JcDV"): MevagentBlocksprint,
|
||||||
|
solana.MustPublicKeyFromBase58("Sp4JHSh9cksfzXbgK7Pq2ovtn8LirLQydaJKTsiNT77"): MevagentBlocksprint,
|
||||||
|
solana.MustPublicKeyFromBase58("Sp1xMS2cbw83SZDNr4AGqkBYYLjb3LvVnmDSrTMaHkr"): MevagentBlocksprint,
|
||||||
|
solana.MustPublicKeyFromBase58("SpagSJmnh8E9cGT5Y431xPPaS2c1xLREGGCWN9yDeUf"): MevagentBlocksprint,
|
||||||
|
solana.MustPublicKeyFromBase58("SpWrza9E63MQuHeGnnfzmtLVCs3pBdjyKPXUABPo9nq"): MevagentBlocksprint,
|
||||||
|
solana.MustPublicKeyFromBase58("moon17L6BgxXRX5uHKudAmqVF96xia9h8ygcmG2sL3F"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moon26Sek222Md7ZydcAGxoKG832DK36CkLrS3PQY4c"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moon7fwyajcVstMoBnVy7UBcTx87SBtNoGGAaH2Cb8V"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonBtH9HvLHjLqi9ivyrMVKgFUsSfrz9BwQ9khhn1u"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonCJg8476LNFLptX1qrK8PdRsA1HD1R6XWyu9MB93"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonF2sz7qwAtdETnrgxNbjonnhGGjd6r4W4UC9284s"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonKfftMiGSak3cezvhEqvkPSzwrmQxQHXuspC96yj"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonQBUKBpkifLcTd78bfxxt4PYLwmJ5admLW6cBBs8"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonXwpKwoVkMegt5Bc776cSW793X1irL5hHV1vJ3JA"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("moonZ6u9E2fgk6eWd82621eLPHt9zuJuYECXAYjMY1C"): MevAgentMoon,
|
||||||
|
solana.MustPublicKeyFromBase58("SpEEdz8S1KorkMZqjMUxfxrmWwofmp6ReNP2Nx6CUmq"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("SpeeDy3GJM4wcrQmk1itRFWgidvxX4rwjTLMv78wwjE"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("SPeEdva37vW8vRtqgYjprQs1g3965icfVN5Rt7SMAyh"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("speEdrSEpox5GUfHWcBc7tQjRuSfUin2yvB7qoYvvJh"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("SPeEDmkHkN3A2roSZf6aZyEMsmrGqTHKqwP51y2Y4rV"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("SpeedLdTJXh2RKpXEaP8JCxkWoUVXhtdPQ1EnxBJMxc"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("SpEediGKLbbXndSYTzwmz6Z3NDgHQLDcTDEvGFkSMH9"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("speede8xCcUq2Tiv1efXeTuE3k9TDNq8TnGKaKSc6J4"): MevAgentSpeedlanding,
|
||||||
|
solana.MustPublicKeyFromBase58("harkEpXoJv5qVzHaN7HSuUAd6PHjyMcFMcDYBMDJCEQ"): MevAgentAllenhark,
|
||||||
|
solana.MustPublicKeyFromBase58("harkm2BTWxZuszoNpZnfe84jRbQTg6KGHaQBmWzDGQQ"): MevAgentAllenhark,
|
||||||
|
solana.MustPublicKeyFromBase58("harkR2YJ4Dpt4UDJTcBirjnSPBhNpQFcoFkNpCkVqNk"): MevAgentAllenhark,
|
||||||
|
solana.MustPublicKeyFromBase58("t3QLYyXH4vZYbEifLqjD581t5dPVhq9LABxWceySzL2"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t46SqGmwStEffUMp1fr2xmv5uyR85TB9annJuLKLf83"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t1TcSg9biJsz4NjKjhopK8QZzPS4KzBgFSszu5QTGgF"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t2XFAFBaUkCzxJwEbLWFX9PKFjfBCp2tSyFtx5z4RZM"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t55hdzzftxWkYy3J8t32C9RRcZDuMZ4LDuBmbTzJFkU"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t6UtTQLUGHJJrzxAb8PBBZdZKra8SWUqvTv9zPnxKNz"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t7qUQU35sLpPydh42BcPmtEfTWW8gBe4Ry3gjwVnokJ"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t8pPgarSK3TnuLbbHmoE1RCQdLxfxuPqNTyFjBKahok"): MevAgentRaiden,
|
||||||
|
solana.MustPublicKeyFromBase58("t96GGdw3MiaGR993XN8PSsRpKGXx56t5Wf6zcF1hBpY"): MevAgentRaiden,
|
||||||
}
|
}
|
||||||
|
|
||||||
var entryContractAddresses = map[solana.PublicKey]string{
|
var entryContractAddresses = map[solana.PublicKey]string{
|
||||||
|
|||||||
6
enum.go
6
enum.go
@@ -15,6 +15,12 @@ const (
|
|||||||
MevAgentSoyas = "soyas"
|
MevAgentSoyas = "soyas"
|
||||||
MevAgentStellium = "stellium"
|
MevAgentStellium = "stellium"
|
||||||
MevAgentAstralane = "astralane"
|
MevAgentAstralane = "astralane"
|
||||||
|
MevagentFa1con = "fa1con"
|
||||||
|
MevagentBlocksprint = "blocksprint"
|
||||||
|
MevAgentMoon = "moon"
|
||||||
|
MevAgentSpeedlanding = "speedlanding"
|
||||||
|
MevAgentAllenhark = "allenhark"
|
||||||
|
MevAgentRaiden = "raiden"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
17
meta.go
17
meta.go
@@ -76,16 +76,31 @@ var (
|
|||||||
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")
|
||||||
|
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")
|
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")
|
||||||
|
meteoraDlmmClaimFee2Discriminator = calculateDiscriminator("global:claim_fee2")
|
||||||
|
meteoraDlmmRebalanceLiquidityDiscriminator = calculateDiscriminator("global:rebalance_liquidity")
|
||||||
meteoraDlmmRemoveLiquidityDiscriminator = calculateDiscriminator("global:remove_liquidity")
|
meteoraDlmmRemoveLiquidityDiscriminator = calculateDiscriminator("global:remove_liquidity")
|
||||||
meteoraDlmmRemoveLiquidity2Discriminator = calculateDiscriminator("global:remove_liquidity2")
|
meteoraDlmmRemoveLiquidity2Discriminator = calculateDiscriminator("global:remove_liquidity2")
|
||||||
meteoraDlmmRemoveLiquidityByRangeDiscriminator = calculateDiscriminator("global:remove_liquidity_by_range")
|
meteoraDlmmRemoveLiquidityByRangeDiscriminator = calculateDiscriminator("global:remove_liquidity_by_range")
|
||||||
meteoraDlmmRemoveLiquidityByRange2Discriminator = calculateDiscriminator("global:remove_liquidity_by_range2")
|
meteoraDlmmRemoveLiquidityByRange2Discriminator = calculateDiscriminator("global:remove_liquidity_by_range2")
|
||||||
meteoraDlmmAddLiquidityEventDiscriminator = calculateDiscriminator("event:AddLiquidity")
|
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")
|
meteoraDlmmRemoveLiquidityEventDiscriminator = calculateDiscriminator("event:RemoveLiquidity")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -202,6 +217,8 @@ const (
|
|||||||
|
|
||||||
raydiumV4SwapBaseInDiscriminator = uint8(9)
|
raydiumV4SwapBaseInDiscriminator = uint8(9)
|
||||||
raydiumV4SwapBaseOutDiscriminator = uint8(11)
|
raydiumV4SwapBaseOutDiscriminator = uint8(11)
|
||||||
|
raydiumV4SwapBaseInV2Discriminator = uint8(16)
|
||||||
|
raydiumV4SwapBaseOutV2Discriminator = uint8(17)
|
||||||
|
|
||||||
raydiumV4AddLiquidityDiscriminator = uint8(3)
|
raydiumV4AddLiquidityDiscriminator = uint8(3)
|
||||||
raydiumV4RemoveLiquidityDiscriminator = uint8(4)
|
raydiumV4RemoveLiquidityDiscriminator = uint8(4)
|
||||||
|
|||||||
852
metaoradlmm.go
852
metaoradlmm.go
@@ -55,6 +55,62 @@ type dlmmRemoveLiquidityEvent struct {
|
|||||||
ActiveBinId int32
|
ActiveBinId int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dlmmPositionCreateEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmPositionCloseEvent struct {
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmClaimFeeInnerEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
FeeX uint64
|
||||||
|
FeeY uint64
|
||||||
|
ActiveBinId int32
|
||||||
|
HasActiveBin bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmClaimFeeEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
FeeX uint64
|
||||||
|
FeeY uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmClaimFee2Event struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
FeeX uint64
|
||||||
|
FeeY uint64
|
||||||
|
ActiveBinId int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmRebalancingEvent struct {
|
||||||
|
LbPair solana.PublicKey
|
||||||
|
Position solana.PublicKey
|
||||||
|
Owner solana.PublicKey
|
||||||
|
ActiveBinId int32
|
||||||
|
XWithdrawnAmount uint64
|
||||||
|
XAddedAmount uint64
|
||||||
|
YWithdrawnAmount uint64
|
||||||
|
YAddedAmount uint64
|
||||||
|
XFeeAmount uint64
|
||||||
|
YFeeAmount uint64
|
||||||
|
OldMinBinId int32
|
||||||
|
OldMaxBinId int32
|
||||||
|
NewMinBinId int32
|
||||||
|
NewMaxBinId int32
|
||||||
|
Rewards [2]uint64
|
||||||
|
}
|
||||||
|
|
||||||
type dlmmBinLiquidityDistribution struct {
|
type dlmmBinLiquidityDistribution struct {
|
||||||
BinId int32
|
BinId int32
|
||||||
DistributionX uint16
|
DistributionX uint16
|
||||||
@@ -127,6 +183,18 @@ type dlmmRemoveLiquidityByRange2Args struct {
|
|||||||
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
RemainingAccountsInfo dlmmRemainingAccountsInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dlmmInitializePositionArgs struct {
|
||||||
|
LowerBinId int32
|
||||||
|
Width int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type dlmmInitializePositionByOperatorArgs struct {
|
||||||
|
LowerBinId int32
|
||||||
|
Width int32
|
||||||
|
FeeOwner solana.PublicKey
|
||||||
|
LockReleasePoint uint64
|
||||||
|
}
|
||||||
|
|
||||||
type dlmmRemainingAccountsInfo struct{}
|
type dlmmRemainingAccountsInfo struct{}
|
||||||
|
|
||||||
func (dlmmRemainingAccountsInfo) UnmarshalWithDecoder(decoder *agbinary.Decoder) error {
|
func (dlmmRemainingAccountsInfo) UnmarshalWithDecoder(decoder *agbinary.Decoder) error {
|
||||||
@@ -200,6 +268,9 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI
|
|||||||
switch discriminator {
|
switch discriminator {
|
||||||
case meteoraInitializeLbPairDiscriminator:
|
case meteoraInitializeLbPairDiscriminator:
|
||||||
return metaoradlmmInitializeParser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmInitializeParser(tx, instruction, innerInstructions, offset)
|
||||||
|
case meteoraDlmmInitializePositionDiscriminator, meteoraDlmmInitializePosition2Discriminator,
|
||||||
|
meteoraDlmmInitializePositionByOperatorDiscriminator, meteoraDlmmInitializePositionPdaDiscriminator:
|
||||||
|
return metaoradlmmPositionCreateParser(tx, instruction, innerInstructions, offset)
|
||||||
case meteoraDlmmSwapDiscriminator, meteoraDlmmSwapExactOutDiscriminator, meteoraDlmmSwapWithPriceImpactDiscriminator:
|
case meteoraDlmmSwapDiscriminator, meteoraDlmmSwapExactOutDiscriminator, meteoraDlmmSwapWithPriceImpactDiscriminator:
|
||||||
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmSwapParser(tx, instruction, innerInstructions, offset)
|
||||||
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
|
case meteoraDlmmSwap2Discriminator, meteoraDlmmSwapExactOut2Discriminator, meteoraDlmmSwapWithPriceImpact2Discriminator:
|
||||||
@@ -207,9 +278,15 @@ func metaoradlmmParser(tx *Tx, instruction Instruction, innerInstructions InnerI
|
|||||||
case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator,
|
case meteoraDlmmAddLiquidityDiscriminator, meteoraDlmmAddLiquidity2Discriminator,
|
||||||
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator:
|
meteoraDlmmAddLiquidityByStrategyDiscriminator, meteoraDlmmAddLiquidityByStrategy2Discriminator:
|
||||||
return metaoradlmmAddLiquidityParser(tx, instruction, innerInstructions, offset)
|
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 meteoraDlmmRemoveLiquidityDiscriminator, meteoraDlmmRemoveLiquidity2Discriminator,
|
||||||
meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
meteoraDlmmRemoveLiquidityByRangeDiscriminator, meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
||||||
return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset)
|
return metaoradlmmRemoveLiquidityParser(tx, instruction, innerInstructions, offset)
|
||||||
|
case meteoraDlmmClosePositionDiscriminator, meteoraDlmmClosePosition2Discriminator, meteoraDlmmClosePositionIfEmptyDiscriminator:
|
||||||
|
return metaoradlmmPositionCloseParser(tx, instruction, innerInstructions, offset)
|
||||||
default:
|
default:
|
||||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
}
|
}
|
||||||
@@ -266,6 +343,141 @@ func metaoradlmmInitializeParser(tx *Tx, instruction Instruction, innerInstructi
|
|||||||
return []Swap{swap}, offset, nil
|
return []Swap{swap}, offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func metaoradlmmPositionCreateParser(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]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decode := instruction.Data
|
||||||
|
if len(decode) < 8 {
|
||||||
|
offset[1] += 1
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm create position instruction data too short, offset, %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
discriminator := *(*[8]byte)(decode[:8])
|
||||||
|
var (
|
||||||
|
lowerBinId int32
|
||||||
|
width int32
|
||||||
|
)
|
||||||
|
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmInitializePositionDiscriminator, meteoraDlmmInitializePosition2Discriminator, meteoraDlmmInitializePositionPdaDiscriminator:
|
||||||
|
var args dlmmInitializePositionArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm create position decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
lowerBinId = args.LowerBinId
|
||||||
|
width = args.Width
|
||||||
|
case meteoraDlmmInitializePositionByOperatorDiscriminator:
|
||||||
|
var args dlmmInitializePositionByOperatorArgs
|
||||||
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm create position by operator decode error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
lowerBinId = args.LowerBinId
|
||||||
|
width = args.Width
|
||||||
|
default:
|
||||||
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, positionAccount, eventUser, err := dlmmPositionCreateInstructionAccounts(result, discriminator, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nextOffset, err
|
||||||
|
}
|
||||||
|
offset = nextOffset
|
||||||
|
|
||||||
|
if !createEvent.LbPair.IsZero() {
|
||||||
|
pool = createEvent.LbPair
|
||||||
|
}
|
||||||
|
if !createEvent.Position.IsZero() {
|
||||||
|
positionAccount = createEvent.Position
|
||||||
|
}
|
||||||
|
if !createEvent.Owner.IsZero() {
|
||||||
|
eventUser = createEvent.Owner
|
||||||
|
}
|
||||||
|
|
||||||
|
swap := Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "open",
|
||||||
|
Pool: pool,
|
||||||
|
User: eventUser,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
StartBinId: lowerBinId,
|
||||||
|
EndBinId: dlmmPositionUpperBinId(lowerBinId, width),
|
||||||
|
PositionAccount: positionAccount,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []Swap{swap}, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func metaoradlmmPositionCloseParser(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]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decode := instruction.Data
|
||||||
|
if len(decode) < 8 {
|
||||||
|
offset[1] += 1
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm close position instruction data too short, offset, %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
discriminator := *(*[8]byte)(decode[:8])
|
||||||
|
pool, positionAccount, eventUser, err := dlmmPositionCloseInstructionAccounts(result, discriminator, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm close position accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
closeEvent, nextOffset, found, err := dlmmPositionCloseEventFromInnerInstructions(innerInstructions, instruction, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nextOffset, err
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
if discriminator == meteoraDlmmClosePositionIfEmptyDiscriminator {
|
||||||
|
return nil, nextOffset, InstructionIgnoredError
|
||||||
|
}
|
||||||
|
return nil, nextOffset, fmt.Errorf("meteora dlmm close position event not found, offset, %d, %d", nextOffset[0], nextOffset[1])
|
||||||
|
}
|
||||||
|
offset = nextOffset
|
||||||
|
|
||||||
|
if !closeEvent.Position.IsZero() {
|
||||||
|
positionAccount = closeEvent.Position
|
||||||
|
}
|
||||||
|
if !closeEvent.Owner.IsZero() {
|
||||||
|
eventUser = closeEvent.Owner
|
||||||
|
}
|
||||||
|
|
||||||
|
swap := Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "close",
|
||||||
|
Pool: pool,
|
||||||
|
User: eventUser,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
PositionAccount: positionAccount,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []Swap{swap}, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
func metaoradlmmSwapParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
func metaoradlmmSwapParser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||||
result := tx.rawTx
|
result := tx.rawTx
|
||||||
|
|
||||||
@@ -457,6 +669,7 @@ func metaoradlmmSwapParser(tx *Tx, instruction Instruction, innerInstructions In
|
|||||||
UserBaseBalance: userBase,
|
UserBaseBalance: userBase,
|
||||||
UserQuoteBalance: userQuote,
|
UserQuoteBalance: userQuote,
|
||||||
EntryContract: entryContract,
|
EntryContract: entryContract,
|
||||||
|
ActiveBinId: swapEvent.EndBinId,
|
||||||
StartBinId: swapEvent.StartBinId,
|
StartBinId: swapEvent.StartBinId,
|
||||||
EndBinId: swapEvent.EndBinId,
|
EndBinId: swapEvent.EndBinId,
|
||||||
}
|
}
|
||||||
@@ -634,7 +847,7 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
|
|||||||
|
|
||||||
swap := Swap{
|
swap := Swap{
|
||||||
Program: SolProgramMeteoraDLMM,
|
Program: SolProgramMeteoraDLMM,
|
||||||
Event: "add_liquidity",
|
Event: "add",
|
||||||
Pool: pool,
|
Pool: pool,
|
||||||
BaseMint: baseMint,
|
BaseMint: baseMint,
|
||||||
QuoteMint: quoteMint,
|
QuoteMint: quoteMint,
|
||||||
@@ -650,9 +863,11 @@ func metaoradlmmAddLiquidityParser(tx *Tx, instruction Instruction, innerInstruc
|
|||||||
UserBaseBalance: userBase,
|
UserBaseBalance: userBase,
|
||||||
UserQuoteBalance: userQuote,
|
UserQuoteBalance: userQuote,
|
||||||
EntryContract: entryContract,
|
EntryContract: entryContract,
|
||||||
|
ActiveBinId: addEvent.ActiveBinId,
|
||||||
StartBinId: startBinId,
|
StartBinId: startBinId,
|
||||||
EndBinId: endBinId,
|
EndBinId: endBinId,
|
||||||
BinChanges: binChanges,
|
BinChanges: binChanges,
|
||||||
|
PositionAccount: result.accountList[accounts.positionIdx],
|
||||||
}
|
}
|
||||||
|
|
||||||
return []Swap{swap}, offset, nil
|
return []Swap{swap}, offset, nil
|
||||||
@@ -682,6 +897,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
binChanges []DlmmBinLiquidityChange
|
binChanges []DlmmBinLiquidityChange
|
||||||
startBinId int32
|
startBinId int32
|
||||||
endBinId int32
|
endBinId int32
|
||||||
|
removeBp int32
|
||||||
)
|
)
|
||||||
|
|
||||||
switch discriminator {
|
switch discriminator {
|
||||||
@@ -692,6 +908,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
}
|
}
|
||||||
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
||||||
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
||||||
|
removeBp = dlmmCommonRemoveBp(args.BinLiquidityRemoval)
|
||||||
case meteoraDlmmRemoveLiquidity2Discriminator:
|
case meteoraDlmmRemoveLiquidity2Discriminator:
|
||||||
var args dlmmRemoveLiquidity2Args
|
var args dlmmRemoveLiquidity2Args
|
||||||
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
@@ -699,6 +916,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
}
|
}
|
||||||
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
binChanges = dlmmBinChangesFromReduction(args.BinLiquidityRemoval)
|
||||||
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
startBinId, endBinId = dlmmMinMaxBinIdFromReduction(args.BinLiquidityRemoval)
|
||||||
|
removeBp = dlmmCommonRemoveBp(args.BinLiquidityRemoval)
|
||||||
case meteoraDlmmRemoveLiquidityByRangeDiscriminator:
|
case meteoraDlmmRemoveLiquidityByRangeDiscriminator:
|
||||||
var args dlmmRemoveLiquidityByRangeArgs
|
var args dlmmRemoveLiquidityByRangeArgs
|
||||||
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
if err := agbinary.NewBorshDecoder(decode[8:]).Decode(&args); err != nil {
|
||||||
@@ -706,6 +924,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
}
|
}
|
||||||
startBinId = args.FromBinId
|
startBinId = args.FromBinId
|
||||||
endBinId = args.ToBinId
|
endBinId = args.ToBinId
|
||||||
|
removeBp = int32(args.BpsToRemove)
|
||||||
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
||||||
case meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
case meteoraDlmmRemoveLiquidityByRange2Discriminator:
|
||||||
var args dlmmRemoveLiquidityByRange2Args
|
var args dlmmRemoveLiquidityByRange2Args
|
||||||
@@ -714,6 +933,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
}
|
}
|
||||||
startBinId = args.FromBinId
|
startBinId = args.FromBinId
|
||||||
endBinId = args.ToBinId
|
endBinId = args.ToBinId
|
||||||
|
removeBp = int32(args.BpsToRemove)
|
||||||
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
binChanges = dlmmBinChangesFromRange(startBinId, endBinId, args.BpsToRemove)
|
||||||
default:
|
default:
|
||||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
@@ -802,7 +1022,7 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
|
|
||||||
swap := Swap{
|
swap := Swap{
|
||||||
Program: SolProgramMeteoraDLMM,
|
Program: SolProgramMeteoraDLMM,
|
||||||
Event: "remove_liquidity",
|
Event: "remove",
|
||||||
Pool: pool,
|
Pool: pool,
|
||||||
BaseMint: baseMint,
|
BaseMint: baseMint,
|
||||||
QuoteMint: quoteMint,
|
QuoteMint: quoteMint,
|
||||||
@@ -818,14 +1038,291 @@ func metaoradlmmRemoveLiquidityParser(tx *Tx, instruction Instruction, innerInst
|
|||||||
UserBaseBalance: userBase,
|
UserBaseBalance: userBase,
|
||||||
UserQuoteBalance: userQuote,
|
UserQuoteBalance: userQuote,
|
||||||
EntryContract: entryContract,
|
EntryContract: entryContract,
|
||||||
|
ActiveBinId: removeEvent.ActiveBinId,
|
||||||
StartBinId: startBinId,
|
StartBinId: startBinId,
|
||||||
EndBinId: endBinId,
|
EndBinId: endBinId,
|
||||||
|
RemoveBp: removeBp,
|
||||||
BinChanges: binChanges,
|
BinChanges: binChanges,
|
||||||
|
PositionAccount: result.accountList[accounts.positionIdx],
|
||||||
}
|
}
|
||||||
|
|
||||||
return []Swap{swap}, offset, nil
|
return []Swap{swap}, offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func metaoradlmmClaimFeeParser(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]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := resolveDlmmClaimFeeAccounts(result, instruction.Data, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm claim fee accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
claimEvent, nextOffset, err := dlmmClaimFeeEventFromInnerInstructions(innerInstructions, instruction, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nextOffset, err
|
||||||
|
}
|
||||||
|
offset = nextOffset
|
||||||
|
if claimEvent.FeeX == 0 && claimEvent.FeeY == 0 {
|
||||||
|
return nil, offset, InstructionIgnoredError
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
baseAmount := decimal.NewFromUint64(claimEvent.FeeX)
|
||||||
|
quoteAmount := decimal.NewFromUint64(claimEvent.FeeY)
|
||||||
|
if !baseIsX {
|
||||||
|
baseTokenProgram = tokenYProgram
|
||||||
|
quoteTokenProgram = tokenXProgram
|
||||||
|
baseReserveIdx = accounts.reserveYIdx
|
||||||
|
quoteReserveIdx = accounts.reserveXIdx
|
||||||
|
userBaseIdx = accounts.userTokenYIdx
|
||||||
|
userQuoteIdx = accounts.userTokenXIdx
|
||||||
|
baseAmount = decimal.NewFromUint64(claimEvent.FeeY)
|
||||||
|
quoteAmount = decimal.NewFromUint64(claimEvent.FeeX)
|
||||||
|
}
|
||||||
|
|
||||||
|
eventUser := result.accountList[accounts.userIdx]
|
||||||
|
if !claimEvent.Owner.IsZero() {
|
||||||
|
eventUser = claimEvent.Owner
|
||||||
|
}
|
||||||
|
|
||||||
|
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: "claim_fee",
|
||||||
|
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,
|
||||||
|
PositionAccount: result.accountList[accounts.positionIdx],
|
||||||
|
}
|
||||||
|
if claimEvent.HasActiveBin {
|
||||||
|
swap.ActiveBinId = claimEvent.ActiveBinId
|
||||||
|
swap.StartBinId = claimEvent.ActiveBinId
|
||||||
|
swap.EndBinId = claimEvent.ActiveBinId
|
||||||
|
}
|
||||||
|
|
||||||
|
return []Swap{swap}, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func metaoradlmmRebalanceLiquidityParser(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]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := resolveDlmmRebalanceAccounts(result, instruction.Accounts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("meteora dlmm rebalance liquidity accounts parse error: %v, offset, %d, %d", err, offset[0], offset[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
event, nextOffset, err := dlmmRebalancingEventFromInnerInstructions(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
|
||||||
|
withdrawBase := event.XWithdrawnAmount
|
||||||
|
withdrawQuote := event.YWithdrawnAmount
|
||||||
|
addBase := event.XAddedAmount
|
||||||
|
addQuote := event.YAddedAmount
|
||||||
|
if !baseIsX {
|
||||||
|
baseTokenProgram = tokenYProgram
|
||||||
|
quoteTokenProgram = tokenXProgram
|
||||||
|
baseReserveIdx = accounts.reserveYIdx
|
||||||
|
quoteReserveIdx = accounts.reserveXIdx
|
||||||
|
userBaseIdx = accounts.userTokenYIdx
|
||||||
|
userQuoteIdx = accounts.userTokenXIdx
|
||||||
|
withdrawBase = event.YWithdrawnAmount
|
||||||
|
withdrawQuote = event.XWithdrawnAmount
|
||||||
|
addBase = event.YAddedAmount
|
||||||
|
addQuote = event.XAddedAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
eventUser := result.accountList[accounts.userIdx]
|
||||||
|
if !event.Owner.IsZero() {
|
||||||
|
eventUser = event.Owner
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var swaps []Swap
|
||||||
|
if withdrawBase > 0 || withdrawQuote > 0 {
|
||||||
|
swaps = append(swaps, Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "remove",
|
||||||
|
Pool: pool,
|
||||||
|
BaseMint: baseMint,
|
||||||
|
QuoteMint: quoteMint,
|
||||||
|
BaseTokenProgram: baseTokenProgram,
|
||||||
|
QuoteTokenProgram: quoteTokenProgram,
|
||||||
|
BaseMintDecimals: baseDecimals,
|
||||||
|
QuoteMintDecimals: quoteDecimals,
|
||||||
|
User: eventUser,
|
||||||
|
BaseAmount: decimal.NewFromUint64(withdrawBase),
|
||||||
|
QuoteAmount: decimal.NewFromUint64(withdrawQuote),
|
||||||
|
BaseReserve: baseReserve,
|
||||||
|
QuoteReserve: quoteReserve,
|
||||||
|
UserBaseBalance: userBase,
|
||||||
|
UserQuoteBalance: userQuote,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
ActiveBinId: event.ActiveBinId,
|
||||||
|
StartBinId: event.OldMinBinId,
|
||||||
|
EndBinId: event.OldMaxBinId,
|
||||||
|
BinChanges: dlmmBinChangesFromRange(event.OldMinBinId, event.OldMaxBinId, 0),
|
||||||
|
PositionAccount: result.accountList[accounts.positionIdx],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if addBase > 0 || addQuote > 0 {
|
||||||
|
swaps = append(swaps, Swap{
|
||||||
|
Program: SolProgramMeteoraDLMM,
|
||||||
|
Event: "add",
|
||||||
|
Pool: pool,
|
||||||
|
BaseMint: baseMint,
|
||||||
|
QuoteMint: quoteMint,
|
||||||
|
BaseTokenProgram: baseTokenProgram,
|
||||||
|
QuoteTokenProgram: quoteTokenProgram,
|
||||||
|
BaseMintDecimals: baseDecimals,
|
||||||
|
QuoteMintDecimals: quoteDecimals,
|
||||||
|
User: eventUser,
|
||||||
|
BaseAmount: decimal.NewFromUint64(addBase),
|
||||||
|
QuoteAmount: decimal.NewFromUint64(addQuote),
|
||||||
|
BaseReserve: baseReserve,
|
||||||
|
QuoteReserve: quoteReserve,
|
||||||
|
UserBaseBalance: userBase,
|
||||||
|
UserQuoteBalance: userQuote,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
ActiveBinId: event.ActiveBinId,
|
||||||
|
StartBinId: event.NewMinBinId,
|
||||||
|
EndBinId: event.NewMaxBinId,
|
||||||
|
BinChanges: dlmmBinChangesFromRange(event.NewMinBinId, event.NewMaxBinId, 0),
|
||||||
|
PositionAccount: result.accountList[accounts.positionIdx],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(swaps) == 0 {
|
||||||
|
return nil, offset, InstructionIgnoredError
|
||||||
|
}
|
||||||
|
|
||||||
|
return swaps, 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 {
|
||||||
@@ -887,6 +1384,116 @@ func dlmmRemoveLiquidityEventFromInnerInstructions(innerInstructions InnerInstru
|
|||||||
return dlmmRemoveLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity event not found, offset, %d, %d", offset[0], prefixLen)
|
return dlmmRemoveLiquidityEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm remove liquidity event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmClaimFeeEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmClaimFeeInnerEvent, [2]uint, error) {
|
||||||
|
var prefixLen = offset[1]
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, prefixLen)
|
||||||
|
if err != nil {
|
||||||
|
return dlmmClaimFeeInnerEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm claim fee get inner instructions error: %v, offset, %d, %d", err, offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
found bool
|
||||||
|
event dlmmClaimFeeInnerEvent
|
||||||
|
matchedIdx int
|
||||||
|
)
|
||||||
|
for innerIndex, innerInstr := range inners {
|
||||||
|
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
decoded, ok := dlmmDecodeClaimFeeEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found = true
|
||||||
|
event = decoded
|
||||||
|
matchedIdx = innerIndex
|
||||||
|
if decoded.HasActiveBin {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return dlmmClaimFeeInnerEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm claim fee event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] = uint(matchedIdx) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmRebalancingEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmRebalancingEvent, [2]uint, error) {
|
||||||
|
var prefixLen = offset[1]
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, prefixLen)
|
||||||
|
if err != nil {
|
||||||
|
return dlmmRebalancingEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm rebalance 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 := dlmmDecodeRebalancingEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] = uint(innerIndex) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, nil
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
for innerIndex, innerInstr := range inners {
|
||||||
|
if innerInstr.ProgramIDIndex != instruction.ProgramIDIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event, ok := dlmmDecodePositionCreateEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] = uint(innerIndex) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, nil
|
||||||
|
}
|
||||||
|
return dlmmPositionCreateEvent{}, increaseOffset(offset), fmt.Errorf("meteora dlmm create position event not found, offset, %d, %d", offset[0], prefixLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmPositionCloseEventFromInnerInstructions(innerInstructions InnerInstructions, instruction Instruction, offset [2]uint) (dlmmPositionCloseEvent, [2]uint, bool, error) {
|
||||||
|
var prefixLen = offset[1]
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, prefixLen)
|
||||||
|
if err != nil {
|
||||||
|
return dlmmPositionCloseEvent{}, increaseOffset(offset), false, fmt.Errorf("meteora dlmm close position 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 := dlmmDecodePositionCloseEvent(innerInstr.Data)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset[1] == 0 {
|
||||||
|
offset[0] += 1
|
||||||
|
} else {
|
||||||
|
offset[1] = uint(innerIndex) + 1 + prefixLen
|
||||||
|
}
|
||||||
|
return event, offset, true, nil
|
||||||
|
}
|
||||||
|
return dlmmPositionCloseEvent{}, increaseOffset(offset), false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func dlmmDecodeAddLiquidityEvent(data []byte) (dlmmAddLiquidityEvent, bool) {
|
func dlmmDecodeAddLiquidityEvent(data []byte) (dlmmAddLiquidityEvent, bool) {
|
||||||
switch {
|
switch {
|
||||||
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmAddLiquidityEventDiscriminator[:]):
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmAddLiquidityEventDiscriminator[:]):
|
||||||
@@ -929,6 +1536,140 @@ func dlmmDecodeRemoveLiquidityEvent(data []byte) (dlmmRemoveLiquidityEvent, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmDecodePositionCreateEvent(data []byte) (dlmmPositionCreateEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmPositionCreateEventDiscriminator[:]):
|
||||||
|
var event dlmmPositionCreateEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[8:]).Decode(&event); err != nil {
|
||||||
|
return dlmmPositionCreateEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmPositionCreateEventDiscriminator[:]):
|
||||||
|
var event dlmmPositionCreateEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmPositionCreateEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
default:
|
||||||
|
return dlmmPositionCreateEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmDecodePositionCloseEvent(data []byte) (dlmmPositionCloseEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmPositionCloseEventDiscriminator[:]):
|
||||||
|
var event dlmmPositionCloseEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[8:]).Decode(&event); err != nil {
|
||||||
|
return dlmmPositionCloseEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmPositionCloseEventDiscriminator[:]):
|
||||||
|
var event dlmmPositionCloseEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmPositionCloseEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
default:
|
||||||
|
return dlmmPositionCloseEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmDecodeClaimFeeEvent(data []byte) (dlmmClaimFeeInnerEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmClaimFee2EventDiscriminator[:]):
|
||||||
|
var event dlmmClaimFee2Event
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmClaimFeeInnerEvent{}, false
|
||||||
|
}
|
||||||
|
return dlmmClaimFeeInnerEvent{
|
||||||
|
LbPair: event.LbPair,
|
||||||
|
Position: event.Position,
|
||||||
|
Owner: event.Owner,
|
||||||
|
FeeX: event.FeeX,
|
||||||
|
FeeY: event.FeeY,
|
||||||
|
ActiveBinId: event.ActiveBinId,
|
||||||
|
HasActiveBin: true,
|
||||||
|
}, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmClaimFeeEventDiscriminator[:]):
|
||||||
|
var event dlmmClaimFeeEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmClaimFeeInnerEvent{}, false
|
||||||
|
}
|
||||||
|
return dlmmClaimFeeInnerEvent{
|
||||||
|
LbPair: event.LbPair,
|
||||||
|
Position: event.Position,
|
||||||
|
Owner: event.Owner,
|
||||||
|
FeeX: event.FeeX,
|
||||||
|
FeeY: event.FeeY,
|
||||||
|
}, true
|
||||||
|
default:
|
||||||
|
return dlmmClaimFeeInnerEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmDecodeRebalancingEvent(data []byte) (dlmmRebalancingEvent, bool) {
|
||||||
|
switch {
|
||||||
|
case len(data) >= 8 && bytes.Equal(data[:8], meteoraDlmmRebalancingEventDiscriminator[:]):
|
||||||
|
var event dlmmRebalancingEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[8:]).Decode(&event); err != nil {
|
||||||
|
return dlmmRebalancingEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
case len(data) >= 16 &&
|
||||||
|
bytes.Equal(data[:8], eventDiscriminator[:]) &&
|
||||||
|
bytes.Equal(data[8:16], meteoraDlmmRebalancingEventDiscriminator[:]):
|
||||||
|
var event dlmmRebalancingEvent
|
||||||
|
if err := agbinary.NewBorshDecoder(data[16:]).Decode(&event); err != nil {
|
||||||
|
return dlmmRebalancingEvent{}, false
|
||||||
|
}
|
||||||
|
return event, true
|
||||||
|
default:
|
||||||
|
return dlmmRebalancingEvent{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmPositionCreateInstructionAccounts(result *RawTx, discriminator [8]byte, accounts []int) (pool, position, owner solana.PublicKey, err error) {
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmInitializePositionDiscriminator, meteoraDlmmInitializePosition2Discriminator:
|
||||||
|
if len(accounts) < 4 {
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("accounts too short, expected at least 4")
|
||||||
|
}
|
||||||
|
return result.accountList[accounts[2]], result.accountList[accounts[1]], result.accountList[accounts[3]], nil
|
||||||
|
case meteoraDlmmInitializePositionByOperatorDiscriminator, meteoraDlmmInitializePositionPdaDiscriminator:
|
||||||
|
if len(accounts) < 5 {
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("accounts too short, expected at least 5")
|
||||||
|
}
|
||||||
|
return result.accountList[accounts[3]], result.accountList[accounts[2]], result.accountList[accounts[4]], nil
|
||||||
|
default:
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("unsupported create position discriminator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmPositionCloseInstructionAccounts(result *RawTx, discriminator [8]byte, accounts []int) (pool, position, owner solana.PublicKey, err error) {
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmClosePositionDiscriminator:
|
||||||
|
if len(accounts) < 5 {
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("accounts too short, expected at least 5")
|
||||||
|
}
|
||||||
|
return result.accountList[accounts[1]], result.accountList[accounts[0]], result.accountList[accounts[4]], nil
|
||||||
|
case meteoraDlmmClosePosition2Discriminator, meteoraDlmmClosePositionIfEmptyDiscriminator:
|
||||||
|
if len(accounts) < 2 {
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("accounts too short, expected at least 2")
|
||||||
|
}
|
||||||
|
return solana.PublicKey{}, result.accountList[accounts[0]], result.accountList[accounts[1]], nil
|
||||||
|
default:
|
||||||
|
return solana.PublicKey{}, solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("unsupported close position discriminator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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")
|
||||||
@@ -1046,6 +1787,93 @@ func resolveDlmmLiquidityAccounts(result *RawTx, accounts []int) (dlmmLiquidityA
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveDlmmClaimFeeAccounts(result *RawTx, data []byte, accounts []int) (dlmmLiquidityAccounts, error) {
|
||||||
|
if len(data) < 8 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("instruction data too short")
|
||||||
|
}
|
||||||
|
discriminator := *(*[8]byte)(data[:8])
|
||||||
|
accountList := result.accountList
|
||||||
|
|
||||||
|
switch discriminator {
|
||||||
|
case meteoraDlmmClaimFee2Discriminator:
|
||||||
|
if len(accounts) < 14 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("accounts too short, expected at least 14")
|
||||||
|
}
|
||||||
|
if !accountList[accounts[12]].Equals(meteoraDlmmEventAuthority) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("event authority mismatch")
|
||||||
|
}
|
||||||
|
if !accountList[accounts[13]].Equals(meteoraDlmmProgram) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("program id mismatch")
|
||||||
|
}
|
||||||
|
return dlmmLiquidityAccounts{
|
||||||
|
positionIdx: accounts[1],
|
||||||
|
poolIdx: accounts[0],
|
||||||
|
userTokenXIdx: accounts[5],
|
||||||
|
userTokenYIdx: accounts[6],
|
||||||
|
reserveXIdx: accounts[3],
|
||||||
|
reserveYIdx: accounts[4],
|
||||||
|
tokenXMintIdx: accounts[7],
|
||||||
|
tokenYMintIdx: accounts[8],
|
||||||
|
userIdx: accounts[2],
|
||||||
|
tokenXProgramIdx: accounts[9],
|
||||||
|
tokenYProgramIdx: accounts[10],
|
||||||
|
}, nil
|
||||||
|
case meteoraDlmmClaimFeeDiscriminator:
|
||||||
|
if len(accounts) < 14 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("accounts too short, expected at least 14")
|
||||||
|
}
|
||||||
|
if !accountList[accounts[12]].Equals(meteoraDlmmEventAuthority) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("event authority mismatch")
|
||||||
|
}
|
||||||
|
if !accountList[accounts[13]].Equals(meteoraDlmmProgram) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("program id mismatch")
|
||||||
|
}
|
||||||
|
return dlmmLiquidityAccounts{
|
||||||
|
positionIdx: accounts[1],
|
||||||
|
poolIdx: accounts[0],
|
||||||
|
userTokenXIdx: accounts[7],
|
||||||
|
userTokenYIdx: accounts[8],
|
||||||
|
reserveXIdx: accounts[5],
|
||||||
|
reserveYIdx: accounts[6],
|
||||||
|
tokenXMintIdx: accounts[9],
|
||||||
|
tokenYMintIdx: accounts[10],
|
||||||
|
userIdx: accounts[4],
|
||||||
|
tokenXProgramIdx: accounts[11],
|
||||||
|
tokenYProgramIdx: accounts[11],
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("unsupported claim fee discriminator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveDlmmRebalanceAccounts(result *RawTx, accounts []int) (dlmmLiquidityAccounts, error) {
|
||||||
|
if len(accounts) < 17 {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("accounts too short, expected at least 17")
|
||||||
|
}
|
||||||
|
accountList := result.accountList
|
||||||
|
|
||||||
|
if !accountList[accounts[15]].Equals(meteoraDlmmEventAuthority) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("event authority mismatch")
|
||||||
|
}
|
||||||
|
if !accountList[accounts[16]].Equals(meteoraDlmmProgram) {
|
||||||
|
return dlmmLiquidityAccounts{}, fmt.Errorf("program id mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
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[9],
|
||||||
|
tokenXProgramIdx: accounts[11],
|
||||||
|
tokenYProgramIdx: accounts[12],
|
||||||
|
}, 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 {
|
||||||
@@ -1182,6 +2010,26 @@ func dlmmBinChangesFromRange(startBinId, endBinId int32, bpsToRemove uint16) []D
|
|||||||
return changes
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dlmmCommonRemoveBp(reduction []dlmmBinLiquidityReduction) int32 {
|
||||||
|
if len(reduction) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
bpsToRemove := reduction[0].BpsToRemove
|
||||||
|
for _, item := range reduction[1:] {
|
||||||
|
if item.BpsToRemove != bpsToRemove {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return int32(bpsToRemove)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlmmPositionUpperBinId(lowerBinId, width int32) int32 {
|
||||||
|
if width <= 0 {
|
||||||
|
return lowerBinId
|
||||||
|
}
|
||||||
|
return lowerBinId + width - 1
|
||||||
|
}
|
||||||
|
|
||||||
func dlmmMinMaxBinIdFromDistribution(dist []dlmmBinLiquidityDistribution) (int32, int32) {
|
func dlmmMinMaxBinIdFromDistribution(dist []dlmmBinLiquidityDistribution) (int32, int32) {
|
||||||
if len(dist) == 0 {
|
if len(dist) == 0 {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|||||||
98
raydiumv4.go
98
raydiumv4.go
@@ -29,6 +29,8 @@ func raydiumV4Parser(tx *Tx, instruction Instruction, innerInstructions InnerIns
|
|||||||
return raydiumv4WithdrawPNLParser(tx, instruction, innerInstructions, offset)
|
return raydiumv4WithdrawPNLParser(tx, instruction, innerInstructions, offset)
|
||||||
case raydiumV4SwapBaseInDiscriminator, raydiumV4SwapBaseOutDiscriminator:
|
case raydiumV4SwapBaseInDiscriminator, raydiumV4SwapBaseOutDiscriminator:
|
||||||
return raydiumv4SwapParser(tx, instruction, innerInstructions, offset)
|
return raydiumv4SwapParser(tx, instruction, innerInstructions, offset)
|
||||||
|
case raydiumV4SwapBaseInV2Discriminator, raydiumV4SwapBaseOutV2Discriminator:
|
||||||
|
return raydiumv4SwapV2Parser(tx, instruction, innerInstructions, offset)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, increaseOffset(offset), InstructionIgnoredError
|
return nil, increaseOffset(offset), InstructionIgnoredError
|
||||||
@@ -397,3 +399,99 @@ func raydiumv4SwapParser(tx *Tx, instruction Instruction, innerInstructions Inne
|
|||||||
},
|
},
|
||||||
}, offset, nil
|
}, offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func raydiumv4SwapV2Parser(tx *Tx, instruction Instruction, innerInstructions InnerInstructions, offset [2]uint) ([]Swap, [2]uint, error) {
|
||||||
|
accountsLen := len(instruction.Accounts)
|
||||||
|
if accountsLen != 8 {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("invalid number of accounts for raydiumv4 swapv2 instruction, offset %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
var entryContract = tx.rawTx.accountList[tx.rawTx.Transaction.Message.Instructions[offset[0]].ProgramIDIndex]
|
||||||
|
|
||||||
|
ammAccount := tx.rawTx.accountList[instruction.Accounts[1]]
|
||||||
|
user := tx.rawTx.accountList[instruction.Accounts[7]]
|
||||||
|
userSourceTokenAccount := tx.rawTx.accountList[instruction.Accounts[5]]
|
||||||
|
userDestinationTokenAccount := tx.rawTx.accountList[instruction.Accounts[6]]
|
||||||
|
baseVaultIdx := instruction.Accounts[3]
|
||||||
|
quoteVaultIdx := instruction.Accounts[4]
|
||||||
|
|
||||||
|
baseTokenbalance, err := getTokenBalanceAfterTx(tx.rawTx, baseVaultIdx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("failed to get base vault balance after tx: %v", err)
|
||||||
|
}
|
||||||
|
quoteTokenbalance, err := getTokenBalanceAfterTx(tx.rawTx, quoteVaultIdx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("failed to get quote vault balance after tx: %v", err)
|
||||||
|
}
|
||||||
|
inners, err := getInnerInstructions(innerInstructions, offset[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, increaseOffset(offset), err
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextIndex int
|
||||||
|
var srcFound, destFound bool
|
||||||
|
var baseAmount, quoteAmount decimal.Decimal
|
||||||
|
var event string
|
||||||
|
for i, inner := range inners {
|
||||||
|
from, to, amount, err := parseTokenTransfer(tx.rawTx, inner)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if from.Equals(userSourceTokenAccount) && !srcFound {
|
||||||
|
if to.Equals(tx.rawTx.accountList[baseVaultIdx]) {
|
||||||
|
event = "sell"
|
||||||
|
baseAmount = decimal.NewFromUint64(amount)
|
||||||
|
srcFound = true
|
||||||
|
} else if to.Equals(tx.rawTx.accountList[quoteVaultIdx]) {
|
||||||
|
event = "buy"
|
||||||
|
quoteAmount = decimal.NewFromUint64(amount)
|
||||||
|
srcFound = true
|
||||||
|
}
|
||||||
|
} else if to.Equals(userDestinationTokenAccount) && !destFound {
|
||||||
|
if from.Equals(tx.rawTx.accountList[quoteVaultIdx]) {
|
||||||
|
event = "sell"
|
||||||
|
quoteAmount = decimal.NewFromUint64(amount)
|
||||||
|
destFound = true
|
||||||
|
} else if from.Equals(tx.rawTx.accountList[baseVaultIdx]) {
|
||||||
|
event = "buy"
|
||||||
|
baseAmount = decimal.NewFromUint64(amount)
|
||||||
|
destFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if srcFound && destFound {
|
||||||
|
nextIndex = i + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !srcFound || !destFound {
|
||||||
|
return nil, increaseOffset(offset), fmt.Errorf("raydiumv4 failed to find token transfer inner instruction for swapv2, offset %d, %d", offset[0], offset[1])
|
||||||
|
}
|
||||||
|
offset[1] += uint(nextIndex + 1)
|
||||||
|
|
||||||
|
userBase := getAccountBalanceAfterTx(tx.rawTx, instruction.Accounts[5])
|
||||||
|
userQuote := getAccountBalanceAfterTx(tx.rawTx, instruction.Accounts[6])
|
||||||
|
baseReserve, _ := decimal.NewFromString(baseTokenbalance.UITokenAmount.Amount)
|
||||||
|
quoteReserve, _ := decimal.NewFromString(quoteTokenbalance.UITokenAmount.Amount)
|
||||||
|
|
||||||
|
return []Swap{
|
||||||
|
{
|
||||||
|
Program: SolProgramRaydiumV4,
|
||||||
|
Event: event,
|
||||||
|
Pool: ammAccount,
|
||||||
|
BaseMint: baseTokenbalance.MintAccount,
|
||||||
|
QuoteMint: quoteTokenbalance.MintAccount,
|
||||||
|
BaseTokenProgram: baseTokenbalance.ProgramIDAccount,
|
||||||
|
QuoteTokenProgram: quoteTokenbalance.ProgramIDAccount,
|
||||||
|
BaseMintDecimals: uint8(baseTokenbalance.UITokenAmount.Decimals),
|
||||||
|
QuoteMintDecimals: uint8(quoteTokenbalance.UITokenAmount.Decimals),
|
||||||
|
User: user,
|
||||||
|
BaseAmount: baseAmount,
|
||||||
|
QuoteAmount: quoteAmount,
|
||||||
|
BaseReserve: baseReserve,
|
||||||
|
QuoteReserve: quoteReserve,
|
||||||
|
Mayhem: false,
|
||||||
|
UserBaseBalance: userBase,
|
||||||
|
UserQuoteBalance: userQuote,
|
||||||
|
EntryContract: entryContract,
|
||||||
|
},
|
||||||
|
}, offset, nil
|
||||||
|
}
|
||||||
|
|||||||
3
tx.go
3
tx.go
@@ -48,9 +48,12 @@ type Swap struct {
|
|||||||
AfterSOLBalance decimal.Decimal
|
AfterSOLBalance decimal.Decimal
|
||||||
|
|
||||||
//For meteora dlmm
|
//For meteora dlmm
|
||||||
|
ActiveBinId int32
|
||||||
StartBinId int32
|
StartBinId int32
|
||||||
EndBinId int32
|
EndBinId int32
|
||||||
|
RemoveBp int32
|
||||||
BinChanges []DlmmBinLiquidityChange
|
BinChanges []DlmmBinLiquidityChange
|
||||||
|
PositionAccount solana.PublicKey
|
||||||
|
|
||||||
ConsumeUnit uint64
|
ConsumeUnit uint64
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user