> ## 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.

# Ephemeral SPL Token 빠른 시작

> ephemeral-rollups-sdk를 사용해 SPL token account를 Ephemeral Rollup에 위임하고 ER에서 전송한 뒤 base layer로 출금합니다.

***

<Tip>
  **AI 코딩 에이전트로 개발하고 계신가요?** MagicBlock Dev Skill을 설치하면 위임 플로우, Magic Actions, Crank, VRF 등 MagicBlock 전용 개발 패턴을 에이전트에 제공할 수 있습니다.

  Claude Code 빠른 설치:

  ```bash theme={null}
  npx add-skill https://github.com/magicblock-labs/magicblock-dev-skill
  ```

  Cursor, Codex, Windsurf, Cline 등 다른 에이전트를 사용하시나요? 모든 설치 방법은 [AI Dev Skill](/ko/pages/overview/additional-information/ai-dev-skill) 페이지를 참고하세요.
</Tip>

### 빠른 접근

예제 확인:

<CardGroup cols={2}>
  <Card title="GitHub" icon="github" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/spl-tokens" iconType="duotone">
    SPL Token Anchor 구현
  </Card>

  <Card title="라이브 예제 앱" icon="coins" href="https://one.magicblock.app/" iconType="duotone">
    프라이빗 결제 체험
  </Card>
</CardGroup>

<Note>
  이 스니펫은 legacy-vault 경로를 사용하는 `@magicblock-labs/ephemeral-rollups-sdk`
  **v0.14.3**을 대상으로 합니다. idempotent-shuttle 경로는 v0.15.3을 대상으로 하므로 하나의
  수명 주기에서는 `delegateSpl` / `undelegateIx` / `withdrawSpl`에 동일한 경로를 사용하세요.
</Note>

***

## 단계별 가이드

Ephemeral SPL Token 프로그램 `SPLxh1LVZzEkX99H6rqYizhytLWPZVV296zyYDPagv2`을 통해
SPL token의 전체 수명 주기를 실행합니다. [위임](/ko/pages/ephemeral-rollups-ers/introduction/ephemeral-accounts)하고,
[ER](/ko/pages/ephemeral-rollups-ers/introduction/ephemeral-rollup)에서 트랜잭션을 실행한 뒤 Solana로 정산합니다:

<Steps>
  <Step title={<a href="#1-delegate">token account 위임</a>}>
    base layer에서 소유자의 잔액을 validator에 위임합니다. mint를 처음 위임할 때 공유
    Global Vault가 생성됩니다.
  </Step>

  <Step title={<a href="#2-transfer">ER에서 전송</a>}>
    rollup 내부의 eATA 간에 token을 공개 또는 프라이빗으로 이동합니다.
  </Step>

  <Step title={<a href="#3-undelegate">위임 해제 및 커밋</a>}>
    ER에서 위임을 해제하고 base layer로 커밋될 때까지 기다립니다.
  </Step>

  <Step title={<a href="#4-withdraw">base layer로 출금</a>}>
    잔액을 Global Vault에서 base-layer token account로 이동합니다.
  </Step>
</Steps>

***

## Ephemeral SPL Token 예제

다음 소프트웨어 패키지가 필요할 수 있으며, 다른 버전도 호환될 수 있습니다.

| 소프트웨어      | 버전      | 설치 가이드                                                     |
| ---------- | ------- | ---------------------------------------------------------- |
| **Solana** | 3.1.9   | [Solana 설치](https://docs.anza.xyz/cli/install)             |
| **Rust**   | 1.89.0  | [Rust 설치](https://www.rust-lang.org/tools/install)         |
| **Anchor** | 1.0.2   | [Anchor 설치](https://www.anchor-lang.com/docs/installation) |
| **Node**   | 24.10.0 | [Node 설치](https://nodejs.org/en/download/current)          |

SDK 설치:

```bash theme={null}
yarn add @magicblock-labs/ephemeral-rollups-sdk@0.14.3
```

### 코드 스니펫

<Tabs>
  <Tab title="1. 위임">
    `delegateSpl`은 소유자의 잔액을 validator에 위임합니다. mint의 첫 위임에서 공유 Global Vault를
    생성하고(`initVaultIfMissing: true`), 이후에는 재사용합니다. **base layer**에서 전송하고
    위임 전에 rent sponsor(`deriveRentPda()`)에 자금을 넣으세요.

    ```typescript theme={null}
    // Legacy vault flow — keep the same idempotent setting across
    // delegateSpl / undelegateIx / withdrawSpl within one lifecycle.
    const delegateOpts = { validator, idempotent: false as const, payer: admin.publicKey };

    const ixs = await delegateSpl(owner.publicKey, mint.publicKey, amount, {
      ...delegateOpts,
      initVaultIfMissing, // true for the first owner of this mint, false after
    });

    await provider.sendAndConfirm(
      new anchor.web3.Transaction().add(...ixs),
      [owner, admin],
      { commitment: "confirmed", skipPreflight: true },
    );
    ```

    [⬆️ 맨 위로](#code-snippets)
  </Tab>

  <Tab title="2. 전송">
    `transferSpl`은 rollup 내부의 eATA 간에 token을 이동합니다. **ephemeral** provider로 전송하세요.
    프라이빗 결제에는 `visibility: "private"`, 일반 고속 전송에는 `"public"`을 설정합니다.

    ```typescript theme={null}
    // Delegation confirms on base before the ER clones the account —
    // poll the ER view before transferring.
    await waitForErTokenAccount(ata, expectedAmount);

    const transferIxs = await transferSpl(
      recipientA.publicKey,
      recipientB.publicKey,
      mint.publicKey,
      2n,
      { visibility: "public", fromBalance: "ephemeral", toBalance: "ephemeral" },
    );

    await providerEphemeralRollup.sendAndConfirm(
      new anchor.web3.Transaction().add(...transferIxs),
      [recipientA],
      { commitment: "confirmed", skipPreflight: true },
    );
    ```

    [⬆️ 맨 위로](#code-snippets)
  </Tab>

  <Tab title="3. 위임 해제">
    ER에서 각 소유자의 위임을 해제하고(트랜잭션당 한 명), 출금 전에
    `GetCommitmentSignature`로 base layer 커밋을 기다립니다.

    ```typescript theme={null}
    const sgn = await providerEphemeralRollup.sendAndConfirm(
      new anchor.web3.Transaction().add(undelegateIx(owner.publicKey, mint.publicKey)),
      [owner],
      { commitment: "confirmed", skipPreflight: true },
    );

    // Wait for the commit back to base before withdrawing, or the withdraw
    // races the commit and fails with InvalidAccountOwner.
    const commit = await GetCommitmentSignature(sgn, providerEphemeralRollup.connection);
    await connection.confirmTransaction(commit, "confirmed");
    ```

    [⬆️ 맨 위로](#code-snippets)
  </Tab>

  <Tab title="4. 출금">
    `withdrawSpl`은 Global Vault의 잔액을 소유자의 base-layer ATA로 되돌립니다.

    ```typescript theme={null}
    const withdrawIxs = await withdrawSpl(owner.publicKey, mint.publicKey, amount, {
      idempotent: false,
    });

    await provider.sendAndConfirm(
      new anchor.web3.Transaction().add(...withdrawIxs),
      [owner],
      { commitment: "confirmed" },
    );
    ```

    [⬆️ 맨 위로](#code-snippets)
  </Tab>

  <Tab title="ER 지원 프로그램">
    SDK helper 대신 자체 프로그램을 통해 ER 측 전송을 라우팅하려면 `#[ephemeral]` 속성을
    추가하세요. 이 instruction은 일반 SPL Token CPI입니다. custody와 PDA 서명 전송은
    [스마트 컨트랙트 통합](/ko/pages/ephemeral-spl-token/smart-contract-integration)을 참조하세요.

    ```rust theme={null}
    use anchor_lang::prelude::*;
    use anchor_spl::token::{self, Token, TokenAccount, Transfer as SplTransfer};
    use ephemeral_rollups_sdk::anchor::ephemeral;

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

        /// Transfer `amount` of SPL tokens from `from` to `to`.
        pub fn transfer(ctx: Context<TransferTokens>, amount: u64) -> Result<()> {
            require!(amount > 0, ErrorCode::InvalidAmount);
            let cpi_accounts = SplTransfer {
                from: ctx.accounts.from.to_account_info(),
                to: ctx.accounts.to.to_account_info(),
                authority: ctx.accounts.payer.to_account_info(),
            };
            let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
            token::transfer(cpi_ctx, amount)?;
            Ok(())
        }
    }
    ```

    [⬆️ 맨 위로](#code-snippets)
  </Tab>
</Tabs>

<Note>
  **로컬 실행:** `yarn` → `yarn build` → `yarn setup`(로컬 base + ER 클러스터를 시작하고
  계속 실행) → 두 번째 터미널에서 `yarn test:local`.
</Note>

***

## Solana 익스플로러

Solana에서의 트랜잭션과 계정 정보를 확인해 보세요.

<CardGroup cols={2}>
  <Card title="Solana 익스플로러" icon="search" href="https://explorer.solana.com/" iconType="duotone">
    공식 Solana 익스플로러
  </Card>

  <Card title="Solscan" icon="searchengin" href="https://solscan.io/" iconType="duotone">
    Solana 블록체인 살펴보기
  </Card>
</CardGroup>

## Solana RPC 제공업체

기존 RPC 제공업체를 통해 트랜잭션과 요청을 전송하세요.

<CardGroup cols={2}>
  <Card title="Solana" icon="star" href="https://solana.com/docs/references/clusters#on-a-high-level" iconType="duotone">
    Free Public Nodes
  </Card>

  <Card title="Helius" icon="sun" href="https://www.helius.dev/solana-rpc-nodes" iconType="duotone">
    Free Shared Nodes
  </Card>

  <Card title="Triton" icon="crystal-ball" href="https://triton.one/solana" iconType="duotone">
    Dedicated High-Performance Nodes
  </Card>
</CardGroup>

## Solana 검증자 대시보드

Solana 검증자 인프라의 실시간 업데이트를 확인하세요.

<CardGroup cols={2}>
  <Card title="Solana Beach" icon="wave" href="https://solanabeach.io/" iconType="duotone">
    Get Validator Insights
  </Card>

  <Card title="Validators App" icon="cloud-binary" href="https://www.validators.app/" iconType="duotone">
    Discover Validator Metrics
  </Card>
</CardGroup>

## 서버 상태

Solana와 MagicBlock의 서버 상태를 확인해 보세요.

<CardGroup cols={2}>
  <Card title="Solana Status" icon="server" href="https://status.solana.com/" iconType="duotone">
    Subscribe to Solana Server Updates
  </Card>

  <Card title="MagicBlock Status" icon="heart-pulse" href="/ko/pages/overview/additional-information/system-status" iconType="duotone">
    Subscribe to MagicBlock Server Status
  </Card>
</CardGroup>

***

## MagicBlock 제품

<CardGroup cols={2}>
  <Card title="에페메럴 롤업(ER)" icon="bolt" href="/ko/pages/ephemeral-rollups-ers/how-to-guide/quickstart" iconType="duotone">
    Solana에서 실시간 무수수료 트랜잭션을 안전하게 실행하세요.
  </Card>

  <Card title="프라이빗 에페메럴 롤업(PER)" icon="shield-check" href="/ko/pages/private-ephemeral-rollups-pers/how-to-guide/quickstart" iconType="duotone">
    규정 준수를 유지하면서 민감한 데이터 보호 — Ephemeral Rollups 위에 구축되었습니다.
  </Card>

  <Card title="Ephemeral SPL Token" icon="coins" href="/ko/pages/ephemeral-spl-token/overview" iconType="duotone">
    rollup 속도로 SPL token을 이동하세요 — 공개 또는 프라이빗 전송, swap, 트레이딩·DeFi 앱용 프라이빗 결제를 지원합니다.
  </Card>

  <Card title="예측 시장 및 트레이딩" icon="chart-line" href="/pages/solutions/prediction-markets" iconType="duotone">
    실시간 실행, session key, token 커스터디, 가격 피드, 자동화, 정산을 결합합니다.
  </Card>

  <Card title="Solana VRF" icon="dice" href="/ko/pages/verifiable-randomness-functions-vrfs/introduction/solana-vrf" iconType="duotone">
    게임, 추첨, 실시간 앱에 증명 가능하게 공정한 온체인 랜덤니스를 추가하세요.
  </Card>

  <Card title="가격 오라클" icon="waveform" href="/ko/pages/tools/oracle/introduction" iconType="duotone">
    트레이딩과 DeFi를 위한 저지연 온체인 가격 피드에 접근하세요.
  </Card>
</CardGroup>

***
