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

# Tongo confidential transfers

> Fund, transfer, and withdraw using Tongo—privacy-preserving balances and transfers with the Tongo SDK

## Overview

Starkzap supports **confidential** (privacy-preserving) transfers through the **[Tongo](https://www.tongo.cash/)** protocol. Using the Tongo SDK, users can perform confidential transfers (amount is obfuscated) on Starknet.

Tongo hides **amounts**. It keeps one encrypted balance per account, proves locally, and returns plain calls that you batch and send from your own account.

<Note>
  Tongo is one of two independent privacy protocols in Starkzap. It is not interchangeable with the [STRK20 privacy pool](/build/starkzap/privacy/strk20) — the two share no interface, so you pick one per integration. If you are still deciding, start with [Choosing a privacy protocol](/build/starkzap/privacy/overview).
</Note>

**What users can do with confidential:**

* 🔐 **Transfer confidentially** - Send to another confidential account by recipient public key; amounts are hidden on-chain
* 📋 **Compliance and auditing** - [Tongo](https://www.tongo.cash/) provides flexible auditing mechanisms that enable compliance without sacrificing user privacy. Through viewing keys and ex-post proving, regulators can verify transaction details while preserving confidentiality for all other parties.
* ⚡ **Ragequit** -- Exit full balance and rollover (activate pending balance)

<Info>
  The Tongo private key is separate from the Starknet wallet key. Your app must create and hold a `TongoConfidential` instance with the user's Tongo key and the correct Tongo contract address for the chain.
</Info>

## Configuration

Create a `TongoConfidential` instance with the Tongo contract for your chain, the user's Tongo private key, and an RPC provider (typically the wallet's provider).

```typescript theme={null}
import { StarkZap, TongoConfidential } from "starkzap";

const sdk = new StarkZap({ network: "mainnet" });
const wallet = await sdk.connectWallet({ account: { signer, accountClass } });

const confidential = await TongoConfidential.create({
  privateKey: tongoPrivateKey,       // BigNumberish or Uint8Array
  contractAddress: TONGO_CONTRACT,  // Address for mainnet or Sepolia
  provider: wallet.getProvider(),
});
```

`create` is async because `@fatsolutions/tongo-sdk` is an optional peer dependency loaded on first use — if it is not installed, this rejects with an install hint instead of breaking the `starkzap` import.

Use the Tongo protocol [documentation](https://docs.tongo.cash/protocol/contracts.html) or deployment list for the correct `contractAddress` per chain. There is no wallet-level "register confidential"; you pass the `TongoConfidential` into the tx builder methods.

<Note>
  Tongo and the [STRK20 privacy pool](/build/starkzap/privacy/strk20) are separate integrations with no shared interface. Tongo keeps an encrypted *balance* per account and proves locally; the pool spends *notes* and needs a remote prover whose output rides on the transaction rather than inside a call. Pick the one you are integrating — there is nothing to code against generically.
</Note>

## TongoConfidential: address and state

**Tongo address (for display or sharing):**

The `address` is a single base58-encoded public key — the recommended value to
share with others so they can send you confidential transfers:

```typescript theme={null}
const tongoAddress = confidential.address; // base58-encoded public key
```

**Recipient identity (for receiving confidential transfers):**

`recipientId` is the same public key expressed as on-chain `{ x, y }`
coordinates. Pass it (or a decoded shared address, see below) as `to` in a
confidential transfer:

```typescript theme={null}
const recipientId = confidential.recipientId; // { x, y } — pass as `to` in confidentialTransfer
```

**Decode a shared address into a recipient:**

When a sender has someone's shareable `address` (the single base58 public key),
`recipientFromAddress` converts it into the `{ x, y }` recipient expected by
`confidentialTransfer` — so users can exchange one public key instead of raw
coordinates:

```typescript theme={null}
const recipient = confidential.recipientFromAddress(theirTongoAddress); // { x, y }
```

**Decrypted state (balance, pending, nonce):**

```typescript theme={null}
const state = await confidential.getState();

console.log("Active balance:", state.balance);   // spendable
console.log("Pending balance:", state.pending);   // needs rollover to become active
console.log("Nonce:", state.nonce);
```

### ConfidentialState shape

```typescript theme={null}
interface ConfidentialState {
  balance: bigint;  // active (spendable)
  pending: bigint;  // pending (activate via rollover)
  nonce: bigint;
}
```

### Unit conversion (optional)

Convert between public ERC20 amounts and confidential (Tongo) units when you need to display or validate amounts:

```typescript theme={null}
const confidentialUnits = await confidential.toConfidentialUnits(Amount.parse("100", USDC));
const publicUnits = await confidential.toPublicUnits(confidentialUnits);
```

## Funding a confidential account

Convert public ERC20 into confidential balance. The tx builder calls the provider's `fund()` method, which returns the approve call (if needed) and the fund call.

```typescript theme={null}
const tx = await wallet
  .tx()
  .confidentialFund(confidential, {
    amount: Amount.parse("100", USDC),
    sender: wallet.address,
  })
  .send();
await tx.wait();
```

Optional: pay a fee to the sender (e.g. for relayed transactions):

```typescript theme={null}
.confidentialFund(confidential, {
  amount: Amount.parse("100", USDC),
  sender: wallet.address,
  feeTo: feeAmount,
})
```

## Confidential transfer

Send from this confidential account to another confidential account. The recipient is identified by their public key — either their `recipientId` (`{ x, y }`) or a shared `address` decoded with `recipientFromAddress`.

```typescript theme={null}
// If you have the recipient's shared Tongo address (base58 public key):
const to = confidential.recipientFromAddress(theirTongoAddress); // { x, y }

const tx = await wallet
  .tx()
  .confidentialTransfer(confidential, {
    amount: Amount.parse("50", USDC),
    to,  // or recipientConfidential.recipientId
    sender: wallet.address,
  })
  .send();
await tx.wait();
```

The transfer generates ZK proofs locally and submits the call on-chain; amounts are not visible on the public ledger.

## Withdrawing to a public address

Convert confidential balance back to ERC20 and send to a Starknet address.

```typescript theme={null}
const tx = await wallet
  .tx()
  .confidentialWithdraw(confidential, {
    amount: Amount.parse("25", USDC),
    to: wallet.address,  // or any Starknet address
    sender: wallet.address,
  })
  .send();
await tx.wait();
```

## Tongo-specific: ragequit and rollover

**Ragequit** — Exit the entire confidential balance to a public address in one call. Use when the user wants to close the confidential account or move everything on-chain.

```typescript theme={null}
const calls = await confidential.ragequit({
  to: wallet.address,
  sender: wallet.address,
});

const tx = await wallet.tx().add(...calls).send();
await tx.wait();
```

**Rollover** — Move pending balance (from received confidential transfers) into the active balance so it can be spent.

```typescript theme={null}
const calls = await confidential.rollover({ sender: wallet.address });
const tx = await wallet.tx().add(...calls).send();
await tx.wait();
```

## Batching with the transaction builder

You can combine confidential operations with transfers, approvals, or other builder methods:

```typescript theme={null}
const tx = await wallet
  .tx()
  .confidentialFund(confidential, { amount: Amount.parse("100", USDC), sender: wallet.address })
  .transfer(USDC, [{ to: anotherAddress, amount: Amount.parse("10", USDC) }])
  .send();
await tx.wait();
```

<Warning>
  Use at most **one** confidential operation per transaction for a given account. Each one is proved against the balance and nonce read when it was built. Once the first applies, the second is stale, and the whole transaction reverts. One confidential operation plus ordinary calls, as above, is fine. Send two confidential operations one after another.
</Warning>

**Builder methods for confidential:**

| Method                                         | Description                                              |
| ---------------------------------------------- | -------------------------------------------------------- |
| `.confidentialFund(confidential, details)`     | Fund confidential account (includes approve when needed) |
| `.confidentialTransfer(confidential, details)` | Transfer to another confidential account                 |
| `.confidentialWithdraw(confidential, details)` | Withdraw to a public Starknet address                    |

Ragequit and rollover are not on the builder; use `confidential.ragequit(...)` / `confidential.rollover(...)` and add the returned calls with `.add(...calls)`.

## Reaching the rest of the Tongo SDK

`TongoConfidential` wraps the operations that produce calls, plus balance reads and unit conversion. Tongo's own `Account` does more than that: transaction history and per-event reads, audit and ex-post proofs, raw encrypted state, and manual decryption.

For any of those, construct the SDK's `Account` yourself with the same values you passed to `create`:

```typescript theme={null}
import { Account } from "@fatsolutions/tongo-sdk";

const tongo = new Account(tongoPrivateKey, TONGO_CONTRACT, wallet.getProvider());

const history = await tongo.getTxHistory(fromBlock);
const incoming = await tongo.getEventsTransferIn(fromBlock);
```

You already hold all three arguments, and the SDK is already installed. A second `Account` instance is safe. It holds no chain state and reads its nonce and balance fresh on every call, so it cannot disagree with the one inside `TongoConfidential`.

## Best practices

1. **Keep the Tongo key separate** from the Starknet wallet key; treat it as sensitive user data and protect it accordingly.
2. **Use the same Tongo contract address** as the rest of your app (same chain) so all operations are consistent.
3. **Check state before withdraw** — ensure `state.balance` (and pending if needed) is sufficient; use `toPublicUnits` / `toConfidentialUnits` if you need to show human-readable amounts.

## Troubleshooting

### Wrong contract or chain

Ensure `contractAddress` matches the [Tongo](https://www.tongo.cash/) deployment for the wallet's chain. A mismatch can lead to failed transactions or wrong state.

### Fund fails or "approve" errors

The provider includes the approve call in `fund()`; if the token or spender is non-standard, you may need to approve manually before calling the builder. Verify the token is the one supported by the Tongo contract.

### Recipient format for confidential transfer

`to` must be a `ConfidentialRecipient` — the object `{ x, y }`. Get it from the recipient's `confidential.recipientId`, or decode their shared base58 Tongo address with `confidential.recipientFromAddress(address)`. Do not pass a Starknet address; use the recipient's Tongo public key.

## Next steps

* [Bitcoin, Stablecoins, and Tokens](/build/starkzap/erc20) — Token presets and amounts
* [Transactions](/build/starkzap/transactions) — Execution options
* [Tx Builder](/build/starkzap/tx-builder) — Batching and builder method list
* [API Reference](/build/starkzap/api-reference) — Full method signatures
