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

# Portal deposits

# Portal Deposit Addresses

Give a user a reusable, public, exchange-style deposit address. Anyone can fund
it with standard ERC-20 transfers, and the funds are credited into the owner's
shielded balance without revealing which account was credited. See
[Portal Deposit Addresses](/sdk/concepts/portal-deposits) for the concept and
trust model.

<Warning>
  **Preview feature — pending external audit, and enabled per deployment.**
  Several fields are launch-limited; see [Launch
  limitations](/sdk/concepts/portal-deposits#launch-limitations).
</Warning>

Android exposes the supported portal lifecycle as methods on your `PrivacyBoost`
instance. `createPortal` derives the portal EOA from the account seed and keeps
the key inside core.

## Lifecycle at a glance

1. **Check support** — `sdk.portalDelegateAddress()`.
2. **Create** — `sdk.createPortal(null)` derives `E`, gaslessly delegates and
   registers it, then publishes discovery.
3. **Share** — senders fund the returned `portal.address` with ordinary ERC-20.
4. **Sweep / credit** — the operator runs this at launch, or you can call
   `sdk.sweepPortal(...)` as a backstop.
5. **Recover** — use `sdk.reclaimPortalDeposit(...)` for uncredited swept
   deposits, then `sdk.withdrawPortal(...)` if raw funds are resting at `E`.

## Check support

```kotlin theme={null}
val delegate = sdk.portalDelegateAddress()
    ?: throw IllegalStateException("This server does not support portal deposits.")
```

## Create a portal

```kotlin theme={null}
val portal = withContext(Dispatchers.IO) {
    sdk.createPortal(index = null) // or index = 0u
}

println(portal.address) // share this public deposit address
println(portal.index)   // seed-derivation index for recovery actions
println(portal.bindH)   // public on-chain binding
```

`createPortal` is resumable. If the same seed-derived portal is already created,
the method returns it as a no-op. Passing an explicit index recreates that
deterministic portal; passing `null` picks the next free index.

## List portals and deposits

```kotlin theme={null}
val portals = withContext(Dispatchers.IO) { sdk.listPortals() }
val deposits = withContext(Dispatchers.IO) { sdk.listPortalDeposits(portal.address) }
val status = withContext(Dispatchers.IO) { sdk.getPortalStatus(portal.address) }
```

<Info>
  `status.delegated` is launch-limited: the server may report `false` even for a
  portal just created by `createPortal`. Do not gate readiness on that field.
</Info>

## Sweep and reclaim

At launch, sweeping is normally operator-run. If you need to trigger it yourself:

```kotlin theme={null}
val txHash = withContext(Dispatchers.IO) {
    sdk.sweepPortal(portal = portal.address, tokenId = tokenId)
}
```

If a swept deposit remains uncredited past the cancel delay:

```kotlin theme={null}
val txHash = withContext(Dispatchers.IO) {
    sdk.reclaimPortalDeposit(depositId = portalDepositId)
}
```

`reclaimPortalDeposit` returns funds to the portal address `E`, not to the caller.
To move raw funds from `E`, build a signed transaction and broadcast it yourself:

```kotlin theme={null}
val rawTx = sdk.withdrawPortal(
    index = portal.index,
    token = tokenAddress,
    to = destination,
    amount = amountWei,
    nonce = nonce,
    gasLimit = gasLimit,
    maxFeePerGas = maxFeePerGasWei,
    maxPriorityFeePerGas = maxPriorityFeePerGasWei
)
```

`E` must hold native gas for the withdrawal transaction.

## Low-level escape hatches

The package still exports two low-level helpers for custodial integrations that
manage their own portal EOA key:

```kotlin theme={null}
val eoa = generatePortalEoa() // privateKey is SECRET
val calldata = encodePortalWithdraw(
    token = tokenAddress,
    to = destination,
    amount = amountWei
)
```

The seed-derived `createPortal` flow does not use or expose `eoa.privateKey`.

## Types

```kotlin theme={null}
data class Portal(
    val address: String,
    val index: UInt,
    val bindH: String
)

data class PortalInfo(
    val address: String,
    val index: UInt?,
    val status: PortalStatus
)

data class PortalStatus(
    val registered: Boolean,
    val delegated: Boolean,
    val published: Boolean
)

data class PortalDeposit(
    val portalDepositId: String,
    val portal: String,
    val tokenId: UShort,
    val grossAmount: String,
    val netAmount: String,
    val state: PortalDepositState,
    val requestBlock: ULong,
    val cancellableAtBlock: ULong
)
```
