Learn how to write a simple Rust program that delegates and increments a counter on Solana
This guide will walk you through the process of writing a simple native Rust program (without Anchor dependencies) that increments a counter. You’ll learn how to deploy this program on Solana and interact with it using a Typescript test script.
Your “Undelegate” instruction must have the exact discriminator. It is never
called by you, instead the validator on the Base Layer will callback with a
CPI into your program after undelegating your account on ER.
In order to delegate the counter PDA, and make it writable in an Ephemeral Rollup session, we need to add an instruction which
internally calls the delegate_account function. delegate_account will CPI to the delegation program, which upon validation will gain ownership of the account.
After this step, an ephemeral validator can start processing transactions on the counter PDA and propose state diff trough the delegation program.
use solana_program::{ account_info::{next_account_info, AccountInfo}, pubkey::Pubkey, entrypoint::ProgramResult, program_error::ProgramError,};use ephemeral_rollups_sdk::ephem::{commit_accounts};// For ER onlypub fn process_commit( _program_id: &Pubkey, accounts: &[AccountInfo],) -> ProgramResult { // Get accounts let account_info_iter = &mut accounts.iter(); let initializer = next_account_info(account_info_iter)?; let counter_account = next_account_info(account_info_iter)?; let magic_program = next_account_info(account_info_iter)?; let magic_context = next_account_info(account_info_iter)?; // Signer should be the same as the initializer if !initializer.is_signer { msg!("Initializer {} should be the signer", initializer.key); return Err(ProgramError::MissingRequiredSignature); } commit_accounts( initializer, vec![counter_account], magic_context, magic_program, )?; Ok(())}
Undelegating the PDA is done by calling the commit_and_undelegate_accounts as part of some instruction.
Undelegation commit the latest state and give back the ownership of the PDA to the owner program. After undelegating and finalizing the state, the validator will create a callback CPI into “undelegate” on the Base Layer.
Build valid transactions that calls your program instructions for delegation and undelegation.
The complete test for this project can be found in the Typescript Test Script.
Create a instruction with the right order and attributes of accounts, and the instruction discriminator for delegation of your program. Send the transaction with the instruction to Base Layer (Solana) network.
Create a instruction with the right order and attributes of accounts, and the instruction discriminator for commit of your program. Send the transaction with the instruction to ER network.
Create a instruction with the right order and attributes of accounts, and the instruction discriminator for undelegation of your program. Send the transaction with the instruction to ER network.
For mainnet, please reach out to the MagicBlock team to receive the appropriate endpoint.
For localhost, download, install, and run the ephemeral validator locally with the appropriate environment variables:
# 1. Install the Local Validatornpm install -g @magicblock-labs/ephemeral-validator# 2. Start the Local ValidatorACCOUNTS_REMOTE=https://rpc.magicblock.app/devnet ACCOUNTS_LIFECYCLE=ephemeral ephemeral-validator# 3. Run the Tests with the Local ValidatorPROVIDER_ENDPOINT=http://localhost:8899 WS_ENDPOINT=ws://localhost:8900 yarn test
Make sure to update your client configuration to use the correct endpoint based on your development or production environment.
Currently the routing to different endpoints needs to be done manually. These
public RPC endpoints are currently free and supported for development: