Simple counter program using Anchor and Ephemeral Rollups.
This program has utilized the following software packages.
| Software | Version | Installation Guide |
|---|---|---|
| Solana | 3.1.9 | Install Solana |
| Rust | 1.89.0 | Install Rust |
| Anchor | 1.0.2 | Install Anchor |
| Node | 24.10.0 | Install Node |
# Check and initialize your Solana version
agave-install list
agave-install init 3.1.9
# Check and initialize your Rust version
rustup show
rustup install 1.89.0
# Check and initialize your Anchor version
avm list
avm use 1.0.2The test script automatically detects the cluster from Anchor.toml and handles Ephemeral Rollup setup for localnet:
yarn
anchor test --skip-deploy --skip-build --skip-local-validatorBuild, deploy and run the tests with new program (note: delete keypairs in /target/deploy folder):
# Delete keypairs in the deploy folder
rm -rf /target/deploy/*.keypair
# Build, deploy and test program
anchor testDelegating an account is the process of transferring the ownership of an account to the delegation program. After delegation, the account can be treated as a regular account in the Ephemeral Rollups, where transactions can be run with low-latency.
Delegation is done by invoking trough CPI the delegate instruction of the delegation program.
-
Add the delegation sdk to your project:
cargo add ephemeral-rollups-sdk
-
Mark your program with
#[delegate]and add the CPI call to one instruction of your program:use ephemeral_rollups_sdk::cpi::delegate_account; use ephemeral_rollups_sdk::er::commit_accounts; use ephemeral_rollups_sdk::anchor::delegate; #[delegate] #[program] pub mod anchor_counter { pub fn delegate(ctx: Context<DelegateInput>) -> Result<()> { let pda_seeds: &[&[u8]] = &[TEST_PDA_SEED]; delegate_account( &ctx.accounts.payer, &ctx.accounts.pda, &ctx.accounts.owner_program, &ctx.accounts.buffer, &ctx.accounts.delegation_record, &ctx.accounts.delegate_account_seeds, &ctx.accounts.delegation_program, &ctx.accounts.system_program, pda_seeds, 0, // max delegation lifetime, 0 means no limit 30000, // commit interval in ms (30s) )?; Ok(()) } }
-
After delegation, you can run transactions on the account with low-latency. Any transaction that would work on the base base layer will work on the delegated account.
-
Add the typescript sdk to your project:
yarn add @magicblock-labs/ephemeral-rollups-sdk
-
Call the instruction to execute the delegation
-
Execute a transaction:
let tx = await program.methods .increment() .accounts({ counter: pda, }) .transaction(); tx.feePayer = providerEphemeralRollup.wallet.publicKey; tx.recentBlockhash = ( await providerEphemeralRollup.connection.getLatestBlockhash() ).blockhash; tx = await providerEphemeralRollup.wallet.signTransaction(tx); const txSign = await providerEphemeralRollup.sendAndConfirm(tx, []); console.log("Increment Tx: ", txSign);
Undelegating an account is the process of transferring the ownership of an account back to the owner program.
You can undelegate with:
const ix = createUndelegateInstruction({
payer: provider.wallet.publicKey,
delegatedAccount: pda,
ownerProgram: program.programId,
reimbursement: provider.wallet.publicKey,
});
let tx = new anchor.web3.Transaction().add(ix);
tx.feePayer = provider.wallet.publicKey;
tx.recentBlockhash = (await provider.connection.getLatestBlockhash()).blockhash;
tx = await provider.wallet.signTransaction(tx);