1. Decoders
  2. Other

Raydium Liquidity Locking decoder

Decode Raydium Liquidity Locking instructions, accounts and events in Rust with the carbon-raydium-liquidity-locking-decoder crate.

On this page

carbon-raydium-liquidity-locking-decoder decodes the instructions, accounts and events of the Raydium Liquidity Locking program (LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE): 4 instructions, 2 account types, 1 event. It is generated with Codama from the program's IDL; see decoders for how decoders plug into a pipeline.

Cratecarbon-raydium-liquidity-locking-decoder 2.0.0
Installcargo add carbon-raydium-liquidity-locking-decoder@2.0.0
Program IDLockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE (carbon_raydium_liquidity_locking_decoder::PROGRAM_ID)
CategoryOther
Decodercarbon_raydium_liquidity_locking_decoder::RaydiumLiquidityLockingDecoder
Instruction enuminstructions::RaydiumLiquidityLockingInstruction
Account enumaccounts::RaydiumLiquidityLockingAccount
Event enuminstructions::CpiEvent
Featuresserde, postgres, graphql (none enabled by default)
API docsdocs.rs/carbon-raydium-liquidity-locking-decoder/2.0.0
Sourcedecoders/raydium-liquidity-locking-decoder

More program decoders without a category: Jupiter DCA, Kamino Farms, Pump Fees, Swig. To decode several in one pipeline, see other program decoders.

The serde feature derives Serialize/Deserialize on every type, postgres adds tables and processors for Postgres, and graphql adds a schema for the GraphQL server.

Usage#

This program crawls recent Raydium Liquidity Locking transactions from the public RPC and prints every decoded CollectClmmFeesAndRewards instruction. Add the dependencies:

Terminal
cargo add carbon-core@2.0.0 carbon-raydium-liquidity-locking-decoder@2.0.0 carbon-rpc-transaction-crawler-datasource@2.0.0 carbon-log-metrics@2.0.0 env_logger tokio --features tokio/full
src/main.rs
use {
    carbon_core::{
        error::CarbonResult, instruction::InstructionProcessorInputType, pipeline::Pipeline,
        processor::Processor,
    },
    carbon_log_metrics::LogMetrics,
    carbon_raydium_liquidity_locking_decoder::{
        instructions::RaydiumLiquidityLockingInstruction, RaydiumLiquidityLockingDecoder,
        PROGRAM_ID,
    },
    carbon_rpc_transaction_crawler_datasource::{ConnectionConfig, Filters, RpcTransactionCrawler},
    std::sync::Arc,
};

#[tokio::main]
async fn main() -> CarbonResult<()> {
    env_logger::init();

    // Fetches the program's recent transactions over JSON-RPC, newest first.
    let datasource = RpcTransactionCrawler::new(
        "https://api.mainnet-beta.solana.com".to_string(),
        PROGRAM_ID,
        ConnectionConfig::default(),
        Filters::new(None, None, None),
        None,
    );

    Pipeline::builder()
        .datasource(datasource)
        .metrics(Arc::new(LogMetrics::new()))
        .instruction(RaydiumLiquidityLockingDecoder, InstructionLogger)
        .build()?
        .run()
        .await
}

struct InstructionLogger;

impl Processor<InstructionProcessorInputType<'_, RaydiumLiquidityLockingInstruction>> for InstructionLogger {
    async fn process(
        &mut self,
        input: &InstructionProcessorInputType<'_, RaydiumLiquidityLockingInstruction>,
    ) -> CarbonResult<()> {
        let signature = input.metadata.transaction_metadata.signature;
        if let RaydiumLiquidityLockingInstruction::CollectClmmFeesAndRewards { data, accounts, .. } = input.decoded_instruction {
            println!("collect_clmm_fees_and_rewards {signature}: {data:?} authority={}", accounts.authority);
        }
        Ok(())
    }
}
Terminal
RUST_LOG=info cargo run

Each CollectClmmFeesAndRewards instruction prints one line with the transaction signature and the decoded CollectClmmFeesAndRewards data. The public endpoint rate-limits requests, so the first lines can take a while; use your own RPC URL for anything beyond a test. See stream with RPC for the crawler options.

Events published with Anchor's emit_cpi! arrive as the CpiEvent instruction. Match them with RaydiumLiquidityLockingInstruction::CpiEvent { data: CpiEvent::SettleCpFeeEvent(event), .. } (import instructions::CpiEvent); see Events. If CpiEvent never arrives, the program logs its events with emit! instead: decode them with decode_log_events.

Decode accounts#

The transaction crawler emits transactions only. To decode accounts, use a datasource that emits account updates. This program subscribes to the program's accounts with programSubscribe on the public WebSocket endpoint and prints every decoded LockedClmmPositionState account as it changes. Add the datasource and the Solana RPC types it takes:

Terminal
cargo add carbon-rpc-program-subscribe-datasource@2.0.0 solana-client@4.2.2
src/main.rs
use {
    carbon_core::{
        account::AccountProcessorInputType, error::CarbonResult, pipeline::Pipeline,
        processor::Processor,
    },
    carbon_log_metrics::LogMetrics,
    carbon_raydium_liquidity_locking_decoder::{
        accounts::RaydiumLiquidityLockingAccount, RaydiumLiquidityLockingDecoder, PROGRAM_ID,
    },
    carbon_rpc_program_subscribe_datasource::{Filters, RpcProgramSubscribe},
    solana_client::rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, UiAccountEncoding},
    std::sync::Arc,
};

#[tokio::main]
async fn main() -> CarbonResult<()> {
    env_logger::init();

    // Streams every change to an account owned by the program (programSubscribe).
    let config = RpcProgramAccountsConfig {
        account_config: RpcAccountInfoConfig {
            encoding: Some(UiAccountEncoding::Base64),
            ..Default::default()
        },
        ..Default::default()
    };
    let datasource = RpcProgramSubscribe::new(
        "wss://api.mainnet-beta.solana.com".to_string(),
        Filters::new(PROGRAM_ID, Some(config)),
    );

    Pipeline::builder()
        .datasource(datasource)
        .metrics(Arc::new(LogMetrics::new()))
        .account(RaydiumLiquidityLockingDecoder, AccountLogger)
        .build()?
        .run()
        .await
}

struct AccountLogger;

impl Processor<AccountProcessorInputType<'_, RaydiumLiquidityLockingAccount>> for AccountLogger {
    async fn process(
        &mut self,
        input: &AccountProcessorInputType<'_, RaydiumLiquidityLockingAccount>,
    ) -> CarbonResult<()> {
        if let RaydiumLiquidityLockingAccount::LockedClmmPositionState(locked_clmm_position_state) = &input.decoded_account.data {
            println!("locked_clmm_position_state {}: {locked_clmm_position_state:?}", input.metadata.pubkey);
        }
        Ok(())
    }
}
Terminal
RUST_LOG=info cargo run

Each update to a LockedClmmPositionState account prints its address and decoded fields; the program runs until you stop it. Cargo resolves solana-client to 4.2.2, the exact version the datasource pins, so both use the same RpcProgramAccountsConfig type. To load every existing account once instead of streaming changes, see load account state.

Instructions#

Variants of RaydiumLiquidityLockingInstruction. Each is RaydiumLiquidityLockingInstruction::<Variant> { program_id, data, accounts }, where data and accounts are the types listed under the variant, exported from carbon_raydium_liquidity_locking_decoder::instructions. Discriminators are the leading bytes of the instruction data, in hex.

How an instruction decodes. The decoder returns a variant only when all of these hold; otherwise the instruction is skipped and no processor is called:

  1. The instruction's program ID is LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE.
  2. The data starts with the variant's discriminator, and the rest deserializes into its data type.
  3. The instruction has at least as many accounts as the variant requires (the "Required accounts" count under each variant).

Accounts. They are matched by position, in the order listed. An account marked optional is None only when the instruction ends before it; Anchor programs pass the program ID as a placeholder for an omitted optional account, so check for Some(PROGRAM_ID) too. Accounts after the listed ones are in accounts.remaining as AccountMetas. The decoder doesn't record whether an account signed or was writable: read that from input.raw_instruction.accounts[i].is_signer and .is_writable, which follow the same order. It doesn't check signer, writable, owner or PDA constraints either; the program enforced those when the transaction executed, so a decoded instruction from a successful transaction already satisfied them.

CollectClmmFeesAndRewards#

From the program's IDL:

collect clmm locked postion fees and rewards

Arguments

  • ctx - The context of accounts

Discriminator 1048fac60ea2d413 · data CollectClmmFeesAndRewards · accounts CollectClmmFeesAndRewardsInstructionAccounts.

No data fields.

Required accounts: 20; extras go to remaining.

Fields of CollectClmmFeesAndRewardsInstructionAccounts, in account order:

#FieldType
0authorityPubkey
1fee_nft_ownerPubkey
2fee_nft_accountPubkey
3locked_positionPubkey
4clmm_programPubkey
5locked_nft_accountPubkey
6personal_positionPubkey
7pool_statePubkey
8protocol_positionPubkey
9token0_vaultPubkey
10token1_vaultPubkey
11tick_array_lowerPubkey
12tick_array_upperPubkey
13recipient_token0_accountPubkey
14recipient_token1_accountPubkey
15token_programPubkey
16token_program2022Pubkey
17memo_programPubkey
18vault0_mintPubkey
19vault1_mintPubkey
20…remainingVec<AccountMeta>

CollectCpFees#

From the program's IDL:

collect cpSwap locked liquidity's fees

Arguments

  • ctx - The context of accounts
  • fee_lp_amount - The amount lp want to claim

Discriminator 081e33c7d1b8f785 · data CollectCpFees · accounts CollectCpFeesInstructionAccounts.

FieldType
fee_lp_amountu64

Required accounts: 18; extras go to remaining.

Fields of CollectCpFeesInstructionAccounts, in account order:

#FieldType
0authorityPubkey
1fee_nft_ownerPubkey
2fee_nft_accountPubkey
3locked_liquidityPubkey
4cp_swap_programPubkey
5cp_authorityPubkey
6pool_statePubkey
7lp_mintPubkey
8recipient_token0_accountPubkey
9recipient_token1_accountPubkey
10token0_vaultPubkey
11token1_vaultPubkey
12vault0_mintPubkey
13vault1_mintPubkey
14locked_lp_vaultPubkey
15token_programPubkey
16token_program2022Pubkey
17memo_programPubkey
18…remainingVec<AccountMeta>

LockClmmPosition#

From the program's IDL:

Lock an existing clmm's position

Arguments

  • ctx - The context of accounts
  • with_metadata - Create NFT with metadata or not

Discriminator bc25b38352965449 · data LockClmmPosition · accounts LockClmmPositionInstructionAccounts.

FieldType
with_metadatabool

Required accounts: 18; extras go to remaining.

Fields of LockClmmPositionInstructionAccounts, in account order:

#FieldType
0authorityPubkey
1payerPubkey
2position_nft_ownerPubkey
3fee_nft_ownerPubkey
4position_nft_accountPubkey
5personal_positionPubkey
6position_nft_mintPubkey
7locked_nft_accountPubkey
8locked_positionPubkey
9fee_nft_mintPubkey
10fee_nft_accountPubkey
11metadata_accountPubkey
12metadata_programPubkey
13associated_token_programPubkey
14rentPubkey
15fee_nft_token_programPubkey
16locked_nft_token_programPubkey
17system_programPubkey
18…remainingVec<AccountMeta>

LockCpLiquidity#

From the program's IDL:

Lock cpSwap liquidity and mint a nft to collect locked liquidity's fee.

Arguments

  • ctx - The context of accounts
  • lp_amount - The lp amount to lock
  • with_metadata - Create NFT with metadata or not

Discriminator d89d1d4e26331f1a · data LockCpLiquidity · accounts LockCpLiquidityInstructionAccounts.

FieldType
lp_amountu64
with_metadatabool

Required accounts: 19; extras go to remaining.

Fields of LockCpLiquidityInstructionAccounts, in account order:

#FieldType
0authorityPubkey
1payerPubkey
2liquidity_ownerPubkey
3fee_nft_ownerPubkey
4fee_nft_mintPubkey
5fee_nft_accountPubkey
6pool_statePubkey
7locked_liquidityPubkey
8lp_mintPubkey
9liquidity_owner_lpPubkey
10locked_lp_vaultPubkey
11token0_vaultPubkey
12token1_vaultPubkey
13metadata_accountPubkey
14rentPubkey
15system_programPubkey
16token_programPubkey
17associated_token_programPubkey
18metadata_programPubkey
19…remainingVec<AccountMeta>

CpiEvent#

Anchor self-CPI that carries one of the program's events. data is the CpiEvent enum.

Discriminator e445a52e51cb9a1d · data CpiEvent · accounts CpiEventInstructionAccounts.

Required accounts: 2; extras go to remaining.

Fields of CpiEventInstructionAccounts, in account order:

#FieldType
0programPubkey
1event_authorityPubkey
2…remainingVec<AccountMeta>

Accounts#

Variants of RaydiumLiquidityLockingAccount. Each wraps a boxed struct from carbon_raydium_liquidity_locking_decoder::accounts::<module>. decode_account only considers accounts owned by PROGRAM_ID and returns the first variant that matches.

LockedClmmPositionState#

Discriminator 34170507aa5a6cd5 · accounts::locked_clmm_position_state::LockedClmmPositionState.

FieldTypeDescription
bump[u8; 1]Bump to identify PDA
position_ownerPubkeyThe owner who has locked clmm NFT
pool_idPubkeyThe ID of the pool with which this record is connected
position_idPubkeyThe ID of the position with which this record is connected
locked_nft_accountPubkeyProgram ATA locked NFT account or user ATA position NFT account
fee_nft_mintPubkeynft mint to check who has authority to collect fee
recent_epochu64account update recent epoch
padding[u64; 8]Unused bytes for future upgrades.

LockedCpLiquidityState#

Discriminator 190aeec5cfea4916 · accounts::locked_cp_liquidity_state::LockedCpLiquidityState.

FieldTypeDescription
locked_lp_amountu64The Locked liquidity amount without claimed lp fee
claimed_lp_amountu64Claimed lp fee amount
unclaimed_lp_amountu64Unclaimed lp fee amount
last_lpu64Last updated cp pool lp total supply
last_ku128Last updated cp pool k
recent_epochu64Account update recent epoch
pool_idPubkeyThe ID of the pool with which this record is connected
fee_nft_mintPubkeynft mint to check who has authority to collect fee
locked_ownerPubkeyThe owner who has locked liquidity
locked_lp_mintPubkeyThe mint of locked lp token
padding[u64; 8]Unused bytes for future upgrades.

Events#

Variants of instructions::CpiEvent, decoded from the CpiEvent instruction. Each wraps a struct from carbon_raydium_liquidity_locking_decoder::events::<module>. The discriminator is the 8-byte event discriminator that follows the e445a52e51cb9a1d CPI-event tag.

SettleCpFeeEvent#

Discriminator 1d4ea505f6a75bf4 · events::settle_cp_fee_event::SettleCpFeeEventEvent.

FieldType
delta_amountu64
unclaimed_amountu64
locked_amountu64
curr_pool_lpu64
last_pool_lpu64
curr_ku128
last_ku128

Types#

Types used by the instructions, accounts and events above, exported from carbon_raydium_liquidity_locking_decoder::types.

SettleCpFeeEvent#

Struct types::settle_cp_fee_event::SettleCpFeeEvent. Same fields as the SettleCpFeeEvent event.

Generated from the crate’s source at Carbon v2.0.0, so it always matches the published code. Spotted a problem? Report it; edits to this page itself are overwritten on the next release.

Your endpoints

Code samples use these instead of the placeholders, so you can copy and run them as they are. They’re stored only in this browser and never sent anywhere.