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

# Deposit

> getATAIntoETADirectDepositorFunction: transfer SPL/Token-2022 tokens from an ATA to an EncryptedTokenAccount. Returns DepositResult with net amount and tx signatures.

## Overview

The `deposit` operation moves tokens from a user's `AssociatedTokenAccount (ATA)` into their `EncryptedTokenAccount (ETA)`. After a successful deposit, the balance is hidden on-chain.

<Steps>
  <Step title="Transfer from ATA">
    Tokens are moved from the user's `AssociatedTokenAccount` into the pool custody account — an on-chain SPL or Token-2022 account controlled by the Umbra program.
  </Step>

  <Step title="Fee Deduction">
    Protocol fees and any Token-2022 transfer fees are subtracted from the incoming amount. The net amount is what gets credited to the ETA.
  </Step>

  <Step title="Credit ETA">
    The net amount is added to the destination user's ETA. The balance is hidden on-chain — it can only be decrypted by the Arcium MPC network and, in Shared mode, by the user's own X25519 key.
  </Step>
</Steps>

<Note>
  The user must be [registered](/sdk/registration) before depositing. An `EncryptedUserAccount` PDA must exist for the destination wallet address.
</Note>

<Warning>
  Deposit transactions are publicly visible on-chain. The depositor's wallet address, the destination address, and the gross transfer amount are all readable from the transaction. Only the resulting ETA balance is hidden — the act of shielding itself is not private.
</Warning>

## Usage

```typescript theme={null}
import { getATAIntoETADirectDepositorFunction } from "@umbra-privacy/sdk/deposit";

const deposit = getATAIntoETADirectDepositorFunction({ client });

const result = await deposit(
  destinationAddress,  // whose encrypted balance to credit
  mint,                // SPL or Token-2022 mint address
  transferAmount,      // amount in native token units (U64)
  options?,            // optional
);
```

## Parameters

<ParamField path="destinationAddress" type="Address" required>
  The wallet address whose ETA is credited. This is usually `client.signer.address` (depositing to yourself), but you can deposit into any registered user's account — the funds will be encrypted under *their* X25519 key.
</ParamField>

<ParamField path="mint" type="Address" required>
  The SPL token mint address. Works with any standard SPL token and Token-2022 mints (see [Token-2022 Support](/advanced/token-2022) for transfer fee handling).
</ParamField>

<ParamField path="transferAmount" type="bigint" required>
  The gross amount to transfer, in the token's native units (accounting for decimals). For example, `1_000_000n` for 1 USDC (6 decimals). Protocol fees and Token-2022 transfer fees are **subtracted** from this amount before the encrypted balance is credited.
</ParamField>

<ParamField path="options.optionalData" type="OptionalData32">
  32 bytes of caller metadata stored with the deposit. Defaults to 32 zero bytes. **Must be a pre-hashed or pre-encrypted 32-byte value** — never store plaintext identifiers.
</ParamField>

<ParamField path="options.accountInfoCommitment" type="Commitment" default="&#x22;confirmed&#x22;">
  Commitment level used for RPC account reads during deposit preparation.
</ParamField>

<ParamField path="options.epochInfoCommitment" type="Commitment" default="&#x22;confirmed&#x22;">
  Commitment level used for fetching epoch info (Token-2022 transfer-fee schedule).
</ParamField>

<ParamField path="options.hooks" type="ATAIntoETADirectDepositHooks">
  Per-phase lifecycle hooks. Keys: `onValidationStart`, `onValidationComplete`, `onMintFetchStart`, `onMintFetchComplete`, `onAccountFetchStart`, `onAccountFetchComplete`, `onArciumSetupStart`, `onArciumSetupComplete`, `onInstructionBuildStart`, `onInstructionBuildComplete`, `queueComputation` (`MpcTransactionStepHooks` — `onPreSend`, `onPostSend`, `onMonitorStarted`, `onProgress`, `onFinalized`, `onRentReclaimSubmitted`, `onRentReclaimError`), `onComplete`, `onError`. Each receives a typed event object.
</ParamField>

<Note>
  There are no `priorityFees`, `awaitCallback`, `skipPreflight`, `maxRetries`, or `purpose` options on the depositor. Priority fees are configured at factory time via `deps.microLamportsPerAcuPolicy`. Callback waiting is always-on for direct deposits — the result's `callback` field is populated on success.
</Note>

## Return Value

Returns a `Promise<DepositResult>`. The `DepositResult` object contains:

```typescript theme={null}
interface DepositResult {
  readonly signatures: readonly TransactionSignature[];   // every tx signature submitted, in order
  readonly queueSignature: TransactionSignature;          // the handler (queue computation) signature
  readonly callback?: CallbackOutcome;                    // present once the callback round-trip completes (always awaited)
  readonly rentClaim?: RentClaimOutcome;                  // rent reclamation outcome (best-effort)
}

type CallbackOutcome =
  | { readonly status: "finalized"; readonly signature?: TransactionSignature; readonly elapsedMs: number }
  | { readonly status: "pruned";    readonly elapsedMs: number }
  | { readonly status: "timed-out"; readonly elapsedMs: number };

type RentClaimOutcome =
  | { readonly claimed: true;  readonly signature: TransactionSignature }
  | { readonly claimed: false; readonly reason: string };
```

* `signatures` — every transaction signature submitted by this call, in submission order (handler, callback, rent claim).
* `queueSignature` — the handler (queue computation) transaction signature.
* `callback` — present once the callback round-trip completes (always awaited) (the default). Discriminated on `status`: `"finalized"` means the callback landed and `signature` is the MPC callback tx signature; `"pruned"` / `"timed-out"` indicate the callback never landed.
* `rentClaim` — present once rent reclamation has been attempted. `{ claimed: true }` returns the rent-reclaim signature; `{ claimed: false }` returns the reason. Rent reclamation is best-effort — the deposit itself still succeeded even when `claimed: false`.

Deposits follow the [dual-instruction pattern](/concepts/how-umbra-works#the-dual-instruction-pattern) - the SDK submits the handler transaction, waits for Arcium to complete the MPC computation, then waits for the callback transaction to confirm.

## Encryption Mode Selection

The SDK automatically selects the correct instruction variant based on the state of the destination user's account:

* **New MXE-only balance** — destination has no X25519 key registered; first deposit.
* **Existing MXE-only balance** — destination has no X25519 key; balance already exists.
* **New Shared balance** — destination has X25519 key registered; first deposit.
* **Existing Shared balance** — destination has X25519 key; balance already exists.

You do not need to specify the mode manually. The destination address's `isUserAccountX25519KeyRegistered` flag drives the selection.

## Protocol Fees

Fees are deducted from the `transferAmount` before crediting the ETA. With the BPS divisor of 16,384:

```
credited = transferAmount - baseFee - floor((transferAmount - baseFee) * commissionBps / 16384)
```

Protocol-fee configuration is set on-chain by the pool admin and may vary per pool. The current default is a small fixed base fee plus a 35-bps commission. See [Pricing](/pricing) for full details.

<Note>
  In most cases, direct deposits from your own ATA to your own ETA carry **zero protocol fees** — the `baseFee` and `commissionBps` are both set to 0 for standard self-shielding. Fees may apply for deposits routed through relayers or for specific pool configurations.
</Note>

## Example: Self-Deposit

```typescript theme={null}
import { getATAIntoETADirectDepositorFunction } from "@umbra-privacy/sdk/deposit";

const deposit = getATAIntoETADirectDepositorFunction({ client });

// Deposit 100 USDC into your own ETA.
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const ONE_HUNDRED_USDC = 100_000_000n; // 6 decimals

const result = await deposit(client.signer.address, USDC, ONE_HUNDRED_USDC);
console.log("Queue signature:", result.queueSignature);
if (result.callback?.status === "finalized") {
  console.log("Callback signature:", result.callback.signature);
}
```

## Example: Deposit to Another User

You can shield tokens directly into another registered user's ETA:

```typescript theme={null}
const RECIPIENT = "GsbwXfJraMomNxBcpR3DBFyKCCmN9SKGzKFJBNKxRFkT";

const result = await deposit(RECIPIENT, USDC, ONE_HUNDRED_USDC);
```

The tokens are encrypted under the recipient's X25519 key. Only they can withdraw them.

## Error Handling

Deposit errors include a `stage` field identifying where the failure occurred:

```typescript theme={null}
import { isEncryptedDepositError } from "@umbra-privacy/sdk/errors";

try {
  await deposit(destinationAddress, mint, amount);
} catch (err) {
  if (isEncryptedDepositError(err)) {
    switch (err.stage) {
      case "validation":
        // Invalid arguments - check destinationAddress, mint, amount
        break;
      case "mint-fetch":
        // Could not fetch mint account - check RPC connectivity and mint address
        break;
      case "fee-calculation":
        // Token-2022 transfer fee calculation failed
        break;
      case "account-fetch":
        // Could not fetch the destination user account or token account
        break;
      case "transaction-send":
        // Transaction submitted but confirmation failed - may still have landed
        break;
      default:
        // Other stages: pda-derivation, instruction-build, transaction-build,
        // transaction-compile, transaction-sign, transaction-validate
        console.error("Deposit failed at stage:", err.stage, err);
    }
  }
}
```

See [Error Handling](/reference/errors) for a full reference.
