> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magicblock.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Anchor サンプル

> Solana 上で counter をインクリメントするシンプルな Anchor プログラムの書き方を学びます

<div
  style={{
position: "relative",
paddingBottom: "56.25%",
height: 0,
overflow: "hidden",
}}
>
  <iframe
    src="https://www.youtube.com/embed/qwu2RBKyFiw?si=PMg-3UbRfvvbrs7C&list=PLWR_ZQiGMS8mIe1kPZe8OfHIbhvZqaM8V"
    title="Build a real-time Anchor Counter on Solana with MagicBlock's Ephemeral Rollup | Tutorial"
    style={{
  position: "absolute",
  top: 0,
  left: 0,
  width: "100%",
  height: "100%",
}}
    frameBorder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    allowFullScreen
    referrerPolicy="strict-origin-when-cross-origin"
  />
</div>

このガイドでは、counter をインクリメントするシンプルな Anchor プログラムの書き方を順を追って説明します。Solana 上にデプロイし、React クライアントから対話する方法も学びます。

## ソフトウェアパッケージ

このプログラムは以下のソフトウェアパッケージで開発・テストされています。他のバージョンでも互換性がある場合があります。

| ソフトウェア     | バージョン  | インストールガイド                                                       |
| ---------- | ------ | --------------------------------------------------------------- |
| **Solana** | 3.1.9  | [Install Solana](https://docs.anza.xyz/cli/install)             |
| **Rust**   | 1.89.0 | [Install Rust](https://www.rust-lang.org/tools/install)         |
| **Anchor** | 1.0.2  | [Install Anchor](https://www.anchor-lang.com/docs/installation) |

## ソースコードへのクイックアクセス

すぐにコードを確認したい場合：

<CardGroup cols={2}>
  <Card title="ソースコード：Anchor Counter プログラム" icon="anchor" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/anchor-counter" iconType="duotone" />

  <Card title="ライブサンプルアプリ" icon="react" href="https://counter-example.magicblock.app/" iconType="duotone" />
</CardGroup>

## Anchor プログラムを書く

counter プログラムの主要な構成要素を順に見ていきましょう：

## コア機能

このプログラムは 2 つの主要な instruction を実装します：

1. `initialize`：counter を 0 にセット
2. `increment`：counter を 1 だけ加算

プログラムの中核構造は以下のとおりです：

```rust theme={null}
#[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
}
```

特別な点はなく、counter をインクリメントするだけのシンプルな Anchor プログラムです。唯一の違いは、委任プログラムと連携するための便利なロジックを注入する `delegate` マクロを追加していることです。

### Counter PDA を委任する

counter PDA を委任し、Ephemeral Rollup セッション内で書き込み可能にするには、内部的に `delegate_account` 関数を呼び出す instruction を追加する必要があります。`delegate_account` は委任プログラムへ CPI を行い、検証が通るとそのアカウントの所有権を取得します。
このステップが完了すると、ephemeral validator が counter PDA に対するトランザクションの処理を開始し、委任プログラムを通じて状態差分を提案できるようになります。

<Card title="トランザクション（Base Layer）：Delegate" icon="magnifying-glass" href="https://solscan.io/tx/5tyEk8gkdP88xe8GL7X12f9WGZfYZtmDbuXozvqkpea4rphXPiNp91vAzmSjsyUR399wimBYazEszKSH35sidPRH?cluster=devnet" iconType="duotone">
  Solana Explorer でトランザクション詳細を確認
</Card>

```rust theme={null}
/// 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>,
}
```

```rust theme={null}
/// 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 できます。これは `commit` intent を持つ `MagicIntentBundleBuilder` を構築して呼び出すことで実現します。

<CardGroup cols={2}>
  <Card title="トランザクション（ER）：Commit" icon="magnifying-glass" href="https://solscan.io/tx/335F5UcgAW3P8wSaVoEPiBoxeykw9wR1kcJLWUnd9sHmxymCgGvLtxaGDy6ZKDgJw2ku9jtRqwVNY85DuAHvs9GT?cluster=custom&customUrl=https://devnet.magicblock.app" iconType="duotone">
    Solana Explorer でトランザクション詳細を確認
  </Card>

  <Card title="トランザクション（Base Layer）：Commit" icon="magnifying-glass" href="https://solscan.io/tx/3xzMGbj2fwFCnGp6r7wyMv5LExmL6SXaEbt52DmxA3Wx1LyksuXpPJS4AAPtqoSeJe3aF7oY3jFNiEhBQKwhzRGN?cluster=devnet" iconType="duotone">
    Solana Explorer でトランザクション詳細を確認
  </Card>
</CardGroup>

```rust theme={null}
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 の所有権が所有者プログラムへ戻されます。

<CardGroup cols={2}>
  <Card title="トランザクション（ER）：Undelegate" icon="magnifying-glass" href="https://solscan.io/tx/3MN6Avygk3FwsuQPoKHzpLo9kBBommHwRHTdgxBooDwsaNHgSYr1yaDXYEe63Eii5DCVbtaK89Yyrhy3dSGhHmvw?cluster=custom&customUrl=https://devnet.magicblock.app" iconType="duotone">
    Solana Explorer でトランザクション詳細を確認
  </Card>

  <Card title="トランザクション（Base Layer）：Undelegate" icon="magnifying-glass" href="https://solscan.io/tx/2YwzNQh632bJu8TSP9GPsXmh7o78KgMMM9QPNbdaAzamtjGZfmT4o7bkG2PtpCWp7aJmmxpxTXr4Qo36k5EjgPab?cluster=devnet" iconType="duotone">
    Solana Explorer でトランザクション詳細を確認
  </Card>
</CardGroup>

```rust theme={null}
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`](https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/anchor-counter/app) にあります。

{" "}

<Card title="ライブサンプルアプリ" icon="react" href="https://counter-example.magicblock.app/" iconType="duotone" />

<iframe src="https://counter-example.magicblock.app/" width="100%" height="500" frameborder="0" />

<Warning>
  iframe は一部のウォレット（例：Backpack）でのみ動作します。代わりに以下のデプロイ済みデモを試してください：[https://counter-example.magicblock.app/](https://counter-example.magicblock.app/)
</Warning>

### Ephemeral エンドポイントの設定

Ephemeral Rollup セッションと対話するには、適切なエンドポイントを設定する必要があります：

* devnet では、以下の ephemeral エンドポイントを使用してください：

  [https://devnet.magicblock.app](https://devnet.magicblock.app)

* mainnet については、適切なエンドポイントを得るために MagicBlock チームへお問い合わせください。

* <a href="/jp/pages/ephemeral-rollups-ers/how-to-guide/local-development">localhost</a> の場合は、ephemeral validator をダウンロード・インストールし、適切な環境変数を指定してローカルで実行してください。

開発環境または本番環境に応じて、クライアントの設定を正しいエンドポイントに更新してください。

<Note>
  これらの公開 RPC エンドポイントは現在無料で、開発用途に利用できます:
  <br /> Magic Router Devnet: [https://devnet-router.magicblock.app](https://devnet-router.magicblock.app) <br />
  Solana Devnet: [https://api.devnet.solana.com](https://api.devnet.solana.com) <br />
  ER Devnet: [https://devnet.magicblock.app](https://devnet.magicblock.app) <br />
  TEE Devnet: [https://devnet-tee.magicblock.app/](https://devnet-tee.magicblock.app/) <br />
  詳細は{" "}
  <a href="/jp/pages/ephemeral-rollups-ers/how-to-guide/local-development">こちら</a>
  をご覧ください。
</Note>

<CardGroup cols={2}>
  <Card title="ソースコード：Anchor Counter プログラム" icon="anchor" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/anchor-counter" iconType="duotone" />

  <Card title="ライブサンプルアプリ" icon="react" href="https://counter-example.magicblock.app/" iconType="duotone" />
</CardGroup>
