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

# Read a Private Balance

> Guide to read a wallet's private balance from the indexer with a full code example.

1. Read fetches encrypted Private Solana Token Accounts from the indexer with dedicated RPC methods.
2. Only the user, or anyone the user authorizes, can decrypt balances with their viewing key.
3. Use it after a private balance changes and before a transfer.

```mermaid theme={"system"}
%%{init: {
  'theme': 'base',
  'themeVariables': {
    'lineColor':           '#FF6B35',
    'primaryTextColor':    '#737373',
    'primaryBorderColor':  '#9CA3AF',
    'actorBkg':            '#FFFFFF',
    'actorBorder':         '#9CA3AF',
    'actorTextColor':      '#737373',
    'signalColor':         '#FF6B35',
    'signalTextColor':     '#737373',
    'labelBoxBkgColor':    '#FF6B351F',
    'labelBoxBorderColor': '#FF6B35',
    'noteBkgColor':        '#F5F5F5',
    'noteTextColor':       '#737373',
    'noteBorderColor':     '#9CA3AF'
  }
}}%%
sequenceDiagram
    participant Wallet
    participant RPC as RPC Provider

    Wallet->>RPC: getShieldedTransactionsByTags
    RPC-->>Wallet: Encrypted transactions
    Note over Wallet: Decrypt
    Note over Wallet: Sum to private balances
```

<Accordion title="Compare to getBalance / getAccount">
  1. `getBalance` returns public SOL. `getAccount` returns a public token account.
  2. The RPC returns the public balance.

  ```mermaid theme={"system"}
  %%{init: {
    'theme': 'base',
    'themeVariables': {
      'lineColor':           '#FF6B35',
      'primaryTextColor':    '#737373',
      'primaryBorderColor':  '#9CA3AF',
      'actorBkg':            '#FFFFFF',
      'actorBorder':         '#9CA3AF',
      'actorTextColor':      '#737373',
      'signalColor':         '#FF6B35',
      'signalTextColor':     '#737373',
      'labelBoxBkgColor':    '#FF6B351F',
      'labelBoxBorderColor': '#FF6B35',
      'noteBkgColor':        '#F5F5F5',
      'noteTextColor':       '#737373',
      'noteBorderColor':     '#9CA3AF'
    }
  }}%%
  sequenceDiagram
      participant Wallet
      participant RPC

      Wallet->>RPC: getBalance / getAccount
      RPC-->>Wallet: Public SOL or token account
  ```
</Accordion>

# Get Started

<Tabs>
  <Tab title="TypeScript Client">
    <Steps>
      <Step>
        ### Prerequisites

        <Info>
          The TypeScript examples require Node.js 24 or later, pnpm 11.18.0, and the Solana CLI.
        </Info>

        ```bash theme={"system"}
        pnpm add @heliuslabs/zolana @solana/kit
        ```

        Source: [sdk-libs/ts](https://github.com/helius-labs/zolana/tree/main/sdk-libs/ts)

        <Accordion title="Connect to Endpoints">
          <Tabs>
            <Tab title="Devnet">
              ```bash theme={"system"}
              pnpm install
              cp .env.example .env
              ```

              Add a [Helius API key](https://dashboard.helius.dev/):

              ```bash .env theme={"system"}
              API_KEY=YOUR_API_KEY
              ZOLANA_PAYER_KEYPAIR=~/.config/solana/id.json
              ```

              ```ts theme={"system"}
              import { createZolanaClient } from "@heliuslabs/zolana";

              const client = await createZolanaClient({
                solanaRpcUrl: "https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY",
                indexerUrl: "http://zolnet-devnet-1779374825.eu-north-1.elb.amazonaws.com",
                proverUrl: "http://zolnet-devnet-1779374825.eu-north-1.elb.amazonaws.com:3001",
                allowInsecureHttp: true,
              });
              ```

              The examples use the Solana CLI wallet as the payer by default. The payer must hold devnet SOL. See [How to Get Devnet SOL](/docs/rpc/devnet-sol).
            </Tab>

            <Tab title="Localnet">
              On localnet the SDK starts the local test validator (`:8899`), Photon indexer (`:8784`), and prover (`:3001`), and the
              client connects to them automatically without needing endpoint configuration.

              ```bash theme={"system"}
              cargo install --git https://github.com/helius-labs/zolana --tag v0.1.0-alpha zolana-cli
              zolana dev start
              ```

              ```ts theme={"system"}
              import { createZolanaClient } from "@heliuslabs/zolana";

              const client = await createZolanaClient({});
              ```
            </Tab>
          </Tabs>
        </Accordion>
      </Step>

      <Step>
        ### Derive the View Tag

        ```typescript theme={"system"}
        import { createZolanaClient } from "@heliuslabs/zolana";

        // The view tag is the sender's Solana public key in confidential rings.
        // Used by the indexer to fetch the sender's UTXOs.
        const senderViewTag =
          senderAddress.confidentialViewTag();
        ```

        * `senderViewTag` is `senderAddress.confidentialViewTag()`, the sender's Solana public key in confidential rings. The indexer uses it to return matching encrypted outputs.
      </Step>

      <Step>
        ### Fetch Transaction Outputs from the Indexer

        ```typescript theme={"system"}
        import { atSlot } from "@heliuslabs/zolana/client";

        const depositResponse =
          await client.getShieldedTransactionsByTags(
            { tags: [senderViewTag] },
            atSlot(depositTx.slot),
          );
        ```

        * `getShieldedTransactionsByTags` fetches the encrypted outputs associated with `senderViewTag`.
        * `atSlot(depositTx.slot)` waits until the indexer has the deposit at that slot.
        * The indexer returns encrypted output data. It does not decrypt the private balance.
      </Step>

      <Step>
        ### Decrypt to a Private Balance

        ```typescript theme={"system"}
        import { SOL_MINT } from "@heliuslabs/zolana";
        import { decryptToBalances } from "@heliuslabs/zolana/transaction";

        const balancesAfterDeposit =
          await decryptToBalances({
            keypair: senderKeypair,
            registry: assets,
            transactions: depositResponse.transactions,
          });
        const depositBalance =
          balancesAfterDeposit.balance(SOL_MINT);
        ```

        * `senderKeypair` supplies the sender's viewing key for local decryption.
        * `decryptToBalances` decrypts matching outputs and returns the sender's private balances.
        * `balancesAfterDeposit.balance(SOL_MINT)` reads the private SOL balance.

        <Note>
          See [Concepts](/docs/privacy/concepts) for how owner tagging and Private Solana Token Accounts work.
        </Note>
      </Step>
    </Steps>

    ### Full Code Example

    Clone and run the example:

    ```bash theme={"system"}
    git clone https://github.com/helius-labs/zolana-examples.git
    cd zolana-examples/typescript-client
    pnpm install
    pnpm example examples/deposit_transfer_withdraw.ts
    ```

    <Info>
      The examples use a confidential Ring on local/devnet [here](https://github.com/helius-labs/zolana-examples/blob/main/typescript-client/examples/deposit_transfer_withdraw.ts).
    </Info>
  </Tab>

  <Tab title="Rust Client">
    <Steps>
      <Step>
        ### Prerequisites

        <Info>
          The Rust examples require the latest stable Rust toolchain and the Solana CLI v4.0.2. See the [Solana installation guide](https://solana.com/docs/intro/installation).
        </Info>

        ```toml Cargo.toml theme={"system"}
        [dependencies]
        zolana-client = { git = "https://github.com/helius-labs/zolana", tag = "v0.1.0-alpha", features = ["indexer-api", "solana-rpc"] }
        zolana-interface = { git = "https://github.com/helius-labs/zolana", tag = "v0.1.0-alpha", features = ["solana"] }
        zolana-keypair = { git = "https://github.com/helius-labs/zolana", tag = "v0.1.0-alpha" }
        zolana-transaction = { git = "https://github.com/helius-labs/zolana", tag = "v0.1.0-alpha" }
        ```

        Source: [sdk-libs/client](https://github.com/helius-labs/zolana/tree/v0.1.0-alpha/sdk-libs/client)

        <Accordion title="Connect to Endpoints">
          <Tabs>
            <Tab title="Devnet">
              Add a [Helius API key](https://dashboard.helius.dev/):

              ```bash .env theme={"system"}
              API_KEY=YOUR_API_KEY
              ZOLANA_PAYER_KEYPAIR=~/.config/solana/id.json
              ```

              ```rust theme={"system"}
              use solana_address::Address;
              use zolana_client::{SolanaRpc, ZolanaClient};
              use zolana_interface::DEFAULT_TREE_ADDRESS;

              let tree: Address = DEFAULT_TREE_ADDRESS.parse()?;
              let client = ZolanaClient::from_urls_allowing_insecure_http(
                  SolanaRpc::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY"),
                  "http://zolnet-devnet-1779374825.eu-north-1.elb.amazonaws.com",
                  "http://zolnet-devnet-1779374825.eu-north-1.elb.amazonaws.com:3001",
                  tree,
              );
              ```

              The examples use the Solana CLI wallet as the payer by default. The payer must hold devnet SOL. See [How to Get Devnet SOL](/docs/rpc/devnet-sol).
            </Tab>

            <Tab title="Localnet">
              ```bash theme={"system"}
              cargo install --git https://github.com/helius-labs/zolana --tag v0.1.0-alpha zolana-cli
              zolana dev start
              ```

              ```rust theme={"system"}
              use solana_address::Address;
              use zolana_client::{SolanaRpc, ZolanaClient};
              use zolana_interface::DEFAULT_TREE_ADDRESS;

              let tree: Address = DEFAULT_TREE_ADDRESS.parse()?;
              let client = ZolanaClient::from_urls(
                  SolanaRpc::new("http://127.0.0.1:8899"),
                  "http://127.0.0.1:8784",
                  "http://127.0.0.1:3001",
                  tree,
              )?;
              ```
            </Tab>
          </Tabs>
        </Accordion>
      </Step>

      <Step>
        ### Derive the View Tag

        ```rust theme={"system"}
        use zolana_client::Rpc;

        let sender_tag = sender_shielded_address.confidential_view_tag()?;
        ```

        * `sender_tag` is `sender_shielded_address.confidential_view_tag()`, the sender's Solana public key in confidential rings. The indexer uses it to return matching encrypted outputs.
      </Step>

      <Step>
        ### Fetch Transaction Outputs from the Indexer

        ```rust theme={"system"}
        use zolana_client::{IndexerRpcConfig, Rpc};

        let response = client.get_shielded_transactions_by_tags(
            vec![sender_tag],
            None,
            Some(50),
            Some(IndexerRpcConfig::at_slot(slot)),
        )?;
        ```

        * `get_shielded_transactions_by_tags` fetches the encrypted outputs associated with `sender_tag`.
        * `IndexerRpcConfig::at_slot(slot)` waits until the indexer has the deposit at that slot.
        * The indexer returns encrypted output data. It does not decrypt the private balance.
      </Step>

      <Step>
        ### Decrypt to a Private Balance

        ```rust theme={"system"}
        use anyhow::anyhow;
        use zolana_transaction::{decrypt_transactions, SOL_MINT};

        let balances = decrypt_transactions(&sender, &response.transactions, &assets)
            .map_err(|e| anyhow!("decrypt sender transactions: {e:?}"))?;
        let sender_balance = balances.get_balance(SOL_MINT);
        ```

        * `sender` supplies the sender's viewing key for local decryption.
        * `decrypt_transactions` decrypts matching outputs and returns the sender's private balances.
        * `get_balance(SOL_MINT)` reads the private SOL balance.
      </Step>
    </Steps>

    ## Full Code Example

    Clone and run the example:

    ```bash theme={"system"}
    git clone https://github.com/helius-labs/zolana-examples.git
    cd zolana-examples/rust-client
    cargo run -p rust-client-example --example deposit_transfer_withdraw
    ```

    <Info>
      The examples use a confidential Ring on local/devnet [here](https://github.com/helius-labs/zolana-examples/blob/main/rust-client/examples/deposit_transfer_withdraw.rs).
    </Info>
  </Tab>
</Tabs>

## Related Guides

<CardGroup cols={2}>
  <Card title="Deposit" icon="arrow-down-to-bracket" href="/docs/privacy/guides/deposit" horizontal />

  <Card title="Transfer" icon="arrow-right-arrow-left" href="/docs/privacy/guides/transfer" horizontal />

  <Card title="Withdraw" icon="arrow-up-from-bracket" href="/docs/privacy/guides/withdraw" horizontal />

  <Card title="Read Private History" icon="clock-rotate-left" href="/docs/privacy/guides/read-history" horizontal />
</CardGroup>

## Didn't find what you were looking for?

<Callout type="info">
  Reach out! [Telegram](https://t.me/tilo_light) | [E-Mail](mailto:sales@helius.xyz) | [Contact](https://www.helius.dev/contact)
</Callout>
