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

iOS 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** — `try await sdk.createPortal(index: nil)` 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

```swift theme={null}
guard let delegate = sdk.portalDelegateAddress() else {
    print("This server does not support portal deposits.")
    return
}
```

## Create a portal

```swift theme={null}
let portal = try await sdk.createPortal(index: nil) // or index: 0

print(portal.address) // share this public deposit address
print(portal.index)   // seed-derivation index for recovery actions
print(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 `nil` picks the next free index.

## List portals and deposits

```swift theme={null}
let portals = try await sdk.listPortals()
let deposits = try await sdk.listPortalDeposits(portal: portal.address)
let status = try await sdk.getPortalStatus(portal: 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:

```swift theme={null}
let txHash = try await sdk.sweepPortal(portal: portal.address, tokenId: tokenId)
```

If a swept deposit remains uncredited past the cancel delay:

```swift theme={null}
let txHash = try await 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:

```swift theme={null}
let rawTx = try 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:

```swift theme={null}
let eoa = generatePortalEoa() // privateKey is SECRET
let calldata = try encodePortalWithdraw(
    token: tokenAddress,
    to: destination,
    amount: amountWei
)
```

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

## Types

```swift theme={null}
struct Portal {
    let address: String
    let index: UInt32
    let bindH: String
}

struct PortalInfo {
    let address: String
    let index: UInt32?
    let status: PortalStatus
}

struct PortalStatus {
    let registered: Bool
    let delegated: Bool
    let published: Bool
}

struct PortalDeposit {
    let portalDepositId: String
    let portal: String
    let tokenId: UInt16
    let grossAmount: String
    let netAmount: String
    let state: PortalDepositState
    let requestBlock: UInt64
    let cancellableAtBlock: UInt64
}
```
