跳转到主要内容
本指南将带你编写一个简单的 Anchor 程序,用来递增计数器。你将学习如何把这个程序部署到 Solana 上,并通过 React 客户端与之交互。

软件包

该程序使用以下软件包开发和测试。其他软件版本也可能兼容。
软件版本安装指南
Solana3.1.9安装 Solana
Rust1.89.0安装 Rust
Anchor1.0.2安装 Anchor

快速查看源代码

如果你想直接进入代码:

源代码:Anchor Counter 程序

在线示例应用

编写 Anchor 程序

下面我们来拆解这个计数器程序的关键组成部分:

核心功能

该程序实现了两个主要 instruction:
  1. initialize:将计数器设为 0
  2. increment:将计数器加 1
下面是程序的核心结构:
#[ephemeral]
#[program]
pub mod public_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(())
    }

    // ... Additional instructions will be added here
}
这里没有什么特别之处,只是一个简单的、用于递增计数器的 Anchor 程序。唯一的区别是我们引入了 delegate 宏,用来注入与委托程序交互所需的逻辑。

委托 Counter PDA

为了将 counter PDA 委托出去,使其在 Ephemeral Rollup 会话中变为可写,我们需要添加一个内部调用 delegate_account 函数的 instruction。delegate_account 会通过 CPI 调用委托程序,验证通过后会接管该账户的所有权。 完成这一步后,临时验证者就可以开始处理 counter PDA 上的交易,并通过委托程序提交状态差异。

交易(Base Layer):Delegate

在 Solana Explorer 上查看交易详情
/// Add delegate function to the context
#[delegate]
#[derive(Accounts)]
pub struct DelegateInput<'info> {
    pub payer: Signer<'info>,
    /// CHECK The pda to delegate
    #[account(mut, del)]
    pub pda: AccountInfo<'info>,
}
/// Delegate the account to the delegation program
/// Set specific validator based on ER, see https://docs.magicblock.gg/pages/ephemeral-rollups-ers/how-to-guide/local-development
pub fn delegate(ctx: Context<DelegateInput>) -> Result<()> {
    ctx.accounts.delegate_pda(
        &ctx.accounts.payer,
        &[COUNTER_SEED],
        DelegateConfig {
            // Optionally set a specific validator from the first remaining account
            validator: ctx.remaining_accounts.first().map(|acc| acc.key()),
            ..Default::default()
        },
    )?;
    Ok(())
}

在 PDA 已被委托时进行 commit

Ephemeral 运行时允许在 PDA 处于委托状态时提交其状态。这通过构建一个带有 commit intent 的 MagicIntentBundleBuilder 并执行它来完成。

交易(ER):Commit

在 Solana Explorer 上查看交易详情

交易(Base Layer):Commit

在 Solana Explorer 上查看交易详情
use ephemeral_rollups_sdk::ephem::MagicIntentBundleBuilder;

/// Increment the counter and manually commit the account in the Ephemeral Rollup session.
pub fn increment_and_commit(ctx: Context<IncrementAndCommit>) -> Result<()> {
    let counter = &mut ctx.accounts.counter;
    counter.count += 1;
    // Serialize the Anchor account before the CPI sees it
    counter.exit(&crate::ID)?;
    MagicIntentBundleBuilder::new(
        ctx.accounts.payer.to_account_info(),
        ctx.accounts.magic_context.to_account_info(),
        ctx.accounts.magic_program.to_account_info(),
    )
    .commit(&[ctx.accounts.counter.to_account_info()])
    .build_and_invoke()?;
    Ok(())
}

解除 PDA 的委托

解除 PDA 委托是通过构建一个带有 commit_and_undelegate intent 的 MagicIntentBundleBuilder 来完成的。 该操作会提交最新状态,并将 PDA 的所有权交还给所属程序。

交易(ER):Undelegate

在 Solana Explorer 上查看交易详情

交易(Base Layer):Undelegate

在 Solana Explorer 上查看交易详情
use ephemeral_rollups_sdk::ephem::MagicIntentBundleBuilder;

/// Undelegate the account from the delegation program
pub fn undelegate(ctx: Context<IncrementAndCommit>) -> Result<()> {
    MagicIntentBundleBuilder::new(
        ctx.accounts.payer.to_account_info(),
        ctx.accounts.magic_context.to_account_info(),
        ctx.accounts.magic_program.to_account_info(),
    )
    .commit_and_undelegate(&[ctx.accounts.counter.to_account_info()])
    .build_and_invoke()?;
    Ok(())
}

接入 React 客户端

React 客户端是一个简单的界面,让你可以与 Anchor 程序进行交互。 它使用 Anchor 绑定与程序通信,并通过 MagicBlock SDK 与 Ephemeral Rollup 会话交互。源代码与程序放在一起,位于 anchor-counter/app

在线示例应用

iframe 仅适用于部分钱包(如 Backpack)。如果遇到问题,可在此直接体验在线 demo:https://counter-example.magicblock.app/

Ephemeral 端点配置

要与 Ephemeral Rollup 会话进行交互,你需要配置正确的端点:
  • 对于 devnet,使用以下 ephemeral 端点: https://devnet.magicblock.app
  • 对于 mainnet,请联系 MagicBlock 团队获取相应端点。
  • 对于 localhost,请下载并安装 ephemeral validator,并使用相应的环境变量在本地运行。
请确保根据你的开发或生产环境,将客户端配置更新为正确的端点。
这些公共 RPC 端点目前可免费用于开发:
Magic Router Devnet: https://devnet-router.magicblock.app
Solana Devnet: https://api.devnet.solana.com
ER Devnet: https://devnet.magicblock.app
TEE Devnet: https://devnet-tee.magicblock.app/
查看更多详情请点击 这里

源代码:Anchor Counter 程序

在线示例应用