Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/magicblock-labs/magicblock-engine-examples/llms.txt

Use this file to discover all available pages before exploring further.

Quickstart

Get started with Ephemeral Rollups by running the Anchor Counter example. This guide will have you delegating accounts, executing low-latency transactions, and committing state back to Solana in under 10 minutes.

Prerequisites

Before you begin, ensure you have the following tools installed:
SoftwareVersionInstallation Guide
Solana2.3.13Install Solana
Rust1.85.0Install Rust
Anchor0.32.1Install Anchor
Node24.10.0Install Node
Use version managers like agave-install for Solana, rustup for Rust, and avm for Anchor to easily switch between versions.

Verify your installations

# Check and initialize your Solana version
agave-install list
agave-install init 2.3.13

# Check and initialize your Rust version
rustup show
rustup install 1.85.0

# Check and initialize your Anchor version
avm list
avm use 0.32.1

Run the Anchor Counter example

1

Clone the repository

Clone the MagicBlock Engine examples repository:
git clone https://github.com/magicblock-labs/magicblock-engine-examples.git
cd magicblock-engine-examples/anchor-counter
2

Install dependencies

Install the required Node.js packages:
yarn install
The project uses:
  • @coral-xyz/anchor (0.32.1) - Anchor framework
  • @magicblock-labs/ephemeral-rollups-sdk (0.6.5) - Ephemeral Rollups SDK
3

Build and deploy

Build the program and deploy it to the configured cluster:
anchor build
anchor deploy
If you want to deploy with a fresh program ID, delete the keypair first:
rm -rf target/deploy/*.keypair
anchor build
4

Run the tests

Execute the test suite to see delegation, execution, and commits in action:
anchor test --skip-deploy --skip-build --skip-local-validator
You’ll see output showing:
  • Counter initialization on Solana base layer
  • Account delegation to Ephemeral Rollup
  • Fast increment transactions on the ER
  • State commits back to Solana
  • Account undelegation

Understanding the code

The Counter program

The Anchor Counter program demonstrates the core Ephemeral Rollup pattern:
anchor-counter/programs/anchor-counter/src/lib.rs
use ephemeral_rollups_sdk::anchor::{commit, delegate, ephemeral};

#[ephemeral]
#[program]
pub mod anchor_counter {
    use super::*;

    /// Initialize the counter
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let counter = &mut ctx.accounts.counter;
        counter.count = 0;
        Ok(())
    }

    /// Increment the counter
    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        let counter = &mut ctx.accounts.counter;
        counter.count += 1;
        Ok(())
    }

    /// Delegate account to Ephemeral Rollup
    pub fn delegate(ctx: Context<DelegateInput>) -> Result<()> {
        ctx.accounts.delegate_pda(
            &ctx.accounts.payer,
            &[COUNTER_SEED],
            DelegateConfig::default(),
        )?;
        Ok(())
    }
}
The #[ephemeral] attribute on the program enables Ephemeral Rollup support. The #[delegate] attribute on the context generates delegation boilerplate.

Delegating an account

Delegation transfers account ownership to the delegation program, making it available in the Ephemeral Rollup:
anchor-counter/tests/anchor-counter.ts
const [counterPDA] = anchor.web3.PublicKey.findProgramAddressSync(
  [Buffer.from("counter")],
  program.programId
);

// Delegate the counter to Ephemeral Rollup
let tx = await program.methods
  .delegate()
  .accounts({
    payer: provider.wallet.publicKey,
    pda: counterPDA,
  })
  .transaction();

const txHash = await provider.sendAndConfirm(tx, [provider.wallet.payer]);
console.log("Delegate txHash:", txHash);

Executing on Ephemeral Rollup

Once delegated, transactions execute with millisecond latency:
// Create provider for Ephemeral Rollup
const providerEphemeralRollup = new anchor.AnchorProvider(
  new anchor.web3.Connection(
    process.env.EPHEMERAL_PROVIDER_ENDPOINT || "https://devnet-as.magicblock.app/",
    {
      wsEndpoint: process.env.EPHEMERAL_WS_ENDPOINT || "wss://devnet-as.magicblock.app/"
    }
  ),
  anchor.Wallet.local()
);

// Execute increment on ER - notice the fast execution!
let tx = await program.methods
  .increment()
  .accounts({ counter: counterPDA })
  .transaction();

tx.feePayer = providerEphemeralRollup.wallet.publicKey;
tx.recentBlockhash = (
  await providerEphemeralRollup.connection.getLatestBlockhash()
).blockhash;
tx = await providerEphemeralRollup.wallet.signTransaction(tx);

const txHash = await providerEphemeralRollup.sendAndConfirm(tx);
console.log("ER Increment txHash:", txHash);

Committing state

Commit account state back to Solana:
use ephemeral_rollups_sdk::ephem::commit_accounts;

pub fn commit(ctx: Context<CommitAccounts>) -> Result<()> {
    commit_accounts(
        &ctx.accounts.payer,
        vec![&ctx.accounts.counter.to_account_info()],
        &ctx.accounts.magic_context,
        &ctx.accounts.magic_program,
    )?;
    Ok(())
}

Test output explained

When you run the tests, you’ll see timing comparisons:
2000ms (Base Layer) Initialize txHash: abc123...
1800ms (Base Layer) Increment txHash: def456...
1500ms (Base Layer) Delegate txHash: ghi789...
45ms (ER) Increment txHash: jkl012...  ← Notice the speed!
50ms (ER) Increment and Commit txHash: mno345...
Ephemeral Rollup transactions execute 40-50x faster than base layer transactions.

Next steps

Core Concepts

Learn how delegation, commits, and transaction routing work

Framework Examples

Explore examples for different Solana frameworks

Local Development

Set up a local Ephemeral Rollup validator

Advanced Examples

Try cranks, Magic Actions, and session keys

Troubleshooting

Wait a few seconds after delegation before executing transactions on the ER. Account propagation takes 2-3 seconds:
await provider.sendAndConfirm(delegateTx);
await new Promise(resolve => setTimeout(resolve, 3000)); // Wait 3s
Make sure you’ve deployed to the correct cluster. Check your Anchor.toml:
[provider]
cluster = "localnet"  # or "devnet"
Then deploy:
anchor deploy --provider.cluster localnet
Ensure all tools match the required versions:
solana --version  # Should be 2.3.13
rustc --version   # Should be 1.85.0
anchor --version  # Should be 0.32.1
node --version    # Should be 24.x
Use version managers to switch versions as needed.
Make sure your wallet has SOL on the target cluster:
# For localnet
solana airdrop 2

# For devnet
solana airdrop 2 --url devnet
The Ephemeral Rollups are currently in testing. Contact the MagicBlock team on Discord to get access to the testing endpoint.

Build docs developers (and LLMs) love