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

# Api reference

# API Reference

Complete API reference for the Privacy Boost React Native SDK (version
`0.2.14`). Everything below is derived from the generated UniFFI bindings —
signatures match what consumers actually see.

***

## Module exports

```typescript theme={null}
import {
  PrivacyBoost,
  PrivacyBoostConfig,
  ChainContextHandle,
  ChainContextConfig,
  KeySource,
  SdkError,
  SdkError_Tags,
  AuthResult,
  sdkVersion,
  generateMnemonic,
  buildShieldPayload,
  finalizeShield,
} from '@sunnyside-io/privacy-boost-react-native';
```

Top-level functions:

```typescript theme={null}
sdkVersion(): string          // Current SDK version string
generateMnemonic(): string    // Random BIP-39 12-word mnemonic
```

See [Stateless shield helpers](#stateless-shield-helpers) for `buildShieldPayload`
and `finalizeShield`.

***

## PrivacyBoost

Main SDK class. One instance per app; hold it in a module-level ref or a
context provider.

### Constructor

```typescript theme={null}
new PrivacyBoost(config: PrivacyBoostConfig)
```

Configs are created via the factory:

```typescript theme={null}
const config = PrivacyBoostConfig.create({
  serverUrl: 'https://indexer.example.com',
  chainId: undefined,                   // discovered from server if omitted
  shieldContractAddress: undefined,     // discovered from server if omitted
  wethContractAddress: '0x...' || undefined,
  teePublicKey: undefined,              // discovered from server if omitted
  appId: 'app_...',
  persistenceStorage: undefined, // RN persistence backends are not wired yet
  persistenceUnlock: undefined,  // leave unset on RN
});

const sdk = new PrivacyBoost(config);
```

**Throws:** `SdkError.ConfigError` if initialization fails, including
unsupported persistence storage or passkey unlock configuration.

### State

```typescript theme={null}
sdk.isConnected(): boolean
sdk.isAuthenticated(): boolean
sdk.getPrivacyAddress(): string | undefined
sdk.getMpk(): string | undefined
sdk.getWalletAddress(): string | undefined
sdk.getMnemonic(): string | undefined                   // throws
```

### Authentication

```typescript theme={null}
sdk.authenticate(
  wallet: WalletDelegate,
  keySource: KeySource | undefined,
  tokenProvider: TokenProvider | undefined,
): Promise<AuthResult>
```

Connect a wallet, derive privacy keys, authenticate with the backend.
Returns an `AuthResult` tagged union — see [AuthResult](#authresult) for all
variants and handling.

```typescript theme={null}
sdk.submitCredential(
  credential: string,
  tokenProvider: TokenProvider | undefined,
): Promise<LoginResult>
```

Complete an authentication flow that returned `CredentialRequired`.

```typescript theme={null}
sdk.proceedAfterMnemonic(
  tokenProvider: TokenProvider | undefined,
): Promise<LoginResult>
```

Complete an authentication flow that returned `MnemonicGenerated` (first-time
user). Call this after the user confirms they've saved the recovery phrase.

```typescript theme={null}
sdk.logout(): void                  // End session, clear all state
sdk.clearSession(): void            // Clear JWT only, keep keys for quick re-auth
sdk.deleteVault(): Promise<void>    // Erase persisted vault on the device
```

### Operations

```typescript theme={null}
sdk.shield(tokenAddress: string, amount: string): Promise<ShieldResult>
sdk.prepareShield(tokenAddress: string, amount: string, recipient: string | undefined): Promise<PreparedShield>
sdk.unshield(tokenAddress: string, amount: string, recipient: string): Promise<UnshieldResult>
sdk.send(tokenAddress: string, amount: string, recipientPrivacyAddress: string): Promise<TransferResult>
sdk.unwrapWeth(amount: string, recipientAddress: string): Promise<string>
```

`unwrapWeth` unwraps WETH the user already holds in their wallet back to
native ETH — it does not interact with the shielded pool.

`prepareShield` builds a deposit payload **without submitting it** — for callers
that relay the transaction themselves (a gasless relayer, an EIP-7702 session
key, or a plain raw transaction). It returns the calldata to relay plus the note
commitment; nothing is sent on-chain. Pass `undefined` for `recipient` to shield
to yourself, or a privacy address to shield to someone else. After relaying, pass
the mined receipt to the top-level [`finalizeShield`](#stateless-shield-helpers)
to recover the on-chain request id.

### Status polling

```typescript theme={null}
sdk.getShieldStatus(requestId: string): Promise<ShieldStatus>
sdk.getTransferStatus(id: string): Promise<TransactionStatus>
sdk.getUnshieldStatus(id: string): Promise<TransactionStatus>
```

### Balances & tokens

```typescript theme={null}
sdk.getBalance(tokenAddress: string): Promise<TokenBalance>
sdk.getAllBalances(): Promise<TokenBalance[]>
sdk.getRegisteredTokens(): Promise<RegisteredToken[]>
sdk.getTokenByAddress(address: string): Promise<RegisteredToken>
sdk.getFees(tokenId: number): Promise<FeeRates>
```

### History & notes

```typescript theme={null}
sdk.getTransactionHistory(
  txType: string | undefined,
  limit: number | undefined,
  cursor: string | undefined,
): Promise<TransactionsResult>

sdk.getUnspentNotes(tokenAddress: string | undefined): Promise<UnspentNote[]>
```

### Merkle tree

```typescript theme={null}
sdk.getMerkleTreeStats(): Promise<MerkleTreeStats>
```

### Audit APIs

For auditable operations — returns all-party visible data, not just the
calling user's. Intended for compliance dashboards and regulators, not for
end-user UIs.

```typescript theme={null}
sdk.getAuditTransactions(
  pubkey?: string,
  txType?: string,
  limit?: number,
  offset?: number,
): Promise<AuditTransactionsResult>

sdk.getAuditNotes(
  owner?: string,
  tokenAddress?: string,
  spent?: boolean,
  limit?: number,
  offset?: number,
): Promise<AuditNotesResult>

sdk.getAuditBalances(
  pubkey?: string,
  tokenAddress?: string,
  limit?: number,
  offset?: number,
): Promise<AuditBalancesResult>
```

### App metadata

```typescript theme={null}
sdk.getAppInfo(appIds: string[]): Promise<AppInfoEntry[]>
```

### Session persistence

```typescript theme={null}
sdk.exportSession(): ExportedSession | undefined
sdk.importSession(session: ExportedSession): boolean
```

### Identity lookup

```typescript theme={null}
sdk.resolveIdentity(identifier: string): IdentityResult   // throws
```

### Pending transactions

Local bookkeeping for optimistic UI — not persisted across SDK instances.

```typescript theme={null}
sdk.addPendingTransaction(tx: PendingTransaction): void
sdk.getPendingTransactions(): PendingTransaction[]
sdk.getAllPendingTransactions(): PendingTransaction[]
sdk.refreshPendingTransactions(): Promise<number>       // returns updated count
```

### Chain context

Create a handle scoped to a different chain while sharing the same SDK
identity.

```typescript theme={null}
sdk.createChainContext(config: ChainContextConfig): ChainContextHandle
```

See [ChainContextHandle](#chaincontexthandle) below.

### Utilities

```typescript theme={null}
sdk.isValidAddress(address: string): boolean
sdk.isValidPrivacyAddress(address: string): boolean
sdk.toChecksumAddress(address: string): string | undefined
sdk.parseAmount(amount: string, decimals: number): string    // throws
sdk.formatAmount(wei: string, decimals: number): string      // throws
```

***

## ChainContextHandle

Returned by `sdk.createChainContext()`. Mirrors the main SDK's chain-scoped
operations against a different chain, without requiring a second
authentication.

```typescript theme={null}
ctx.chainId(): bigint
ctx.isAuthenticated(): boolean
ctx.isRegistered(): boolean
ctx.authenticate(wallet: WalletDelegate): Promise<LoginResult>

ctx.shield(tokenAddress: string, amount: string): Promise<ShieldResult>
ctx.prepareShield(tokenAddress: string, amount: string, recipient: string | undefined): Promise<PreparedShield>
ctx.unshield(tokenAddress: string, amount: string, recipient: string): Promise<UnshieldResult>
ctx.send(tokenAddress: string, amount: string, recipientPrivacyAddress: string): Promise<TransferResult>
ctx.unwrapWeth(amount: string, recipient: string): Promise<string>

ctx.getBalance(tokenAddress: string): Promise<TokenBalance>
ctx.getAllBalances(): Promise<TokenBalance[]>
ctx.getRegisteredTokens(): Promise<RegisteredToken[]>
ctx.getTokenByAddress(address: string): Promise<RegisteredToken>
ctx.getFees(tokenId: number): Promise<FeeRates>

ctx.getShieldStatus(requestId: string): Promise<ShieldStatus>
ctx.getTransferStatus(id: string): Promise<TransactionStatus>
ctx.getUnshieldStatus(id: string): Promise<TransactionStatus>

ctx.getTransactionHistory(txType?: string, limit?: number, cursor?: string): Promise<TransactionsResult>
ctx.getUnspentNotes(tokenAddress?: string): Promise<UnspentNote[]>

ctx.addPendingTransaction(tx: PendingTransaction): void
ctx.getPendingTransactions(): PendingTransaction[]
ctx.getAllPendingTransactions(): PendingTransaction[]
ctx.refreshPendingTransactions(): Promise<number>

ctx.clearSession(): void
```

***

## Stateless shield helpers

Top-level named exports for building a deposit payload without a signed-in
session — for a backend that holds only a recipient's privacy address. No
wallet, no private keys.

```typescript theme={null}
import { buildShieldPayload, finalizeShield } from '@sunnyside-io/privacy-boost-react-native';

buildShieldPayload(
  tokenAddress: string,
  amount: string,
  recipient: string,
  tokenId: number,
  shieldContractAddress: string,
  wethContractAddress: string | undefined,
  teePublicKey: string,
  minShieldAmount: string | undefined,
  emitApprove: boolean,
): PreparedShield

finalizeShield(
  receipt: TransactionReceipt,
  shieldContract: string,
  commitment: string,
): ShieldResult
```

`buildShieldPayload` builds a recipient-targeted deposit payload from public
material only. Resolve `tokenId`, `shieldContractAddress`, and `teePublicKey`
from the token catalog / config. An ephemeral sender keypair is generated and
discarded internally, and the note is spendable only by `recipient`.
`wethContractAddress` is required only when shielding native ETH;
`minShieldAmount` (per-token minimum in wei) rejects below-minimum deposits;
`emitApprove` emits the ERC-20 approve call (pass `true` by default).

`finalizeShield` recovers the on-chain shield request id from the mined receipt
of a relayed deposit. Stateless — the caller obtained the receipt from its own
relay/RPC. Throws if the deposit reverted or the `DepositRequested` log is
absent. The `TransactionReceipt` is the same shape returned by
`WalletDelegate.waitForTransactionReceipt` (see [WalletDelegate](#walletdelegate)).

***

## Delegate interfaces

### WalletDelegate

```typescript theme={null}
interface WalletDelegate {
  getAddress(): Promise<string>;
  getChainId(): Promise<bigint>;
  signMessage(message: string): Promise<string>;
  signTypedData(typedDataJson: string): Promise<string>;
  sendTransaction(toAddress: string, value: string, data: string): Promise<string>;
  waitForTransactionReceipt(txHash: string): Promise<TransactionReceipt>;
}

interface TransactionReceipt {
  txHash: string;
  status: boolean;
  logs: Array<{ address: string; topics: string[]; data: string }>;
}
```

### TokenProvider

```typescript theme={null}
interface TokenProvider {
  getToken(loginPayloadJson: string): Promise<TokenResponse>;
}

interface TokenResponse {
  token: string;
  expiresIn: bigint;
}
```

***

## Types

### PrivacyBoostConfig

```typescript theme={null}
type PrivacyBoostConfig = {
  serverUrl: string;
  chainId: bigint | undefined;
  shieldContractAddress: string | undefined;
  wethContractAddress: string | undefined;
  teePublicKey: string | undefined;
  appId: string;
  persistenceStorage: StorageBackend | undefined;
  persistenceUnlock: UnlockMethod | undefined;
};
```

React Native currently rejects configured persistence backends at construction.
Keep `persistenceStorage` and `persistenceUnlock` unset until native persistence
is wired through this package.

### ChainContextConfig

```typescript theme={null}
type ChainContextConfig = {
  serverUrl: string;
  chainId: bigint;
  shieldContractAddress: string | undefined;
  wethContractAddress: string | undefined;
  rpcUrl: string | undefined;
  teePublicKey: string | undefined;
  timeoutMs: bigint;
};
```

### KeySource

Tagged union — each variant is constructable.

```typescript theme={null}
new KeySource.WalletDerived()
new KeySource.Mnemonic('twelve word phrase')
new KeySource.RawSeed('0xdeadbeef...')
```

### StorageBackend

```typescript theme={null}
enum StorageBackend {
  LocalStorage = 'LocalStorage',
  IndexedDb = 'IndexedDb',
  OsKeychain = 'OsKeychain',
}
```

These enum values are shared with other SDK targets, but React Native currently
rejects them at construction.

### UnlockMethod

```typescript theme={null}
enum UnlockMethod {
  None = 'None',
  Pin = 'Pin',
  Password = 'Password',
  Biometric = 'Biometric',
  Passkey = 'Passkey',
}
```

`Passkey` is rejected on React Native because iOS and Android do not expose the
WebAuthn PRF extension needed for reproducible vault unlock keys.

### AuthResult

Tagged union returned by `authenticate()`. You must handle all four variants.

```typescript theme={null}
type AuthResult =
  | { tag: 'Authenticated'; loginResult: LoginResult }
  | { tag: 'CredentialRequired'; challenge: CredentialChallenge }
  | { tag: 'MnemonicGenerated'; mnemonic: string }
  | { tag: 'RecoveryRequired'; challenge: RecoveryChallenge };
```

See [Getting Started → Connecting a Wallet](./getting-started#connecting-a-wallet)
for worked handling of each variant.

### LoginResult

```typescript theme={null}
interface LoginResult {
  privacyAddress: string;
  mpk: string;
  isNewUser: boolean;
  chainRegistrations: Map<string, string>;  // chainId → registration tx hash
}
```

### ShieldResult

```typescript theme={null}
interface ShieldResult {
  txHash: string;
  commitment: string;
  requestId: string;
  warning?: string;
  wrapTxHash?: string;   // present when shielding native ETH
}
```

`finalizeShield` also returns a `ShieldResult`.

### Call / PreparedShield

Returned by `prepareShield` and `buildShieldPayload`. Each `Call` is a single
on-chain call to relay; `value` and `data` are 0x-hex.

```typescript theme={null}
interface Call {
  to: string;
  value: string;
  data: string;
}

interface PreparedShield {
  approve?: Call;   // ERC-20 approve(pool, amount); omitted when managed out of band
  wrap?: Call;      // WETH deposit() wrap; present only when shielding native ETH
  shield: Call;     // the requestDeposit(...) call
  commitment: string;
  finalize: { shieldContract: string; tokenId: number };
}
```

### UnshieldResult / TransferResult

```typescript theme={null}
interface UnshieldResult { requestId: string; txHash: string; fee: string; }
interface TransferResult { requestId: string; txHash: string; fee: string; giftRecord?: GiftRecord; claimLink?: string; }
```

### ShieldStatus / TransactionStatus

```typescript theme={null}
interface ShieldStatus {
  id: string;
  status: string;         // "pending" | "confirmed" | "failed" | ...
  createdAt?: string;
  updatedAt?: string;
  txHash?: string;
  leafIndex?: bigint;
  error?: string;
}

interface TransactionStatus {
  id: string;
  txType: string;
  status: string;
  createdAt?: string;
  updatedAt?: string;
  txHash?: string;
  error?: string;
}
```

### TokenBalance

```typescript theme={null}
interface TokenBalance {
  tokenAddress: string;
  shieldedBalance: string;   // in wei
  walletBalance: string;     // in wei
  symbol?: string;
  decimals: number;
}
```

### RegisteredToken

```typescript theme={null}
interface RegisteredToken {
  id: number;
  tokenType: number;
  tokenAddress: string;
  tokenSubId: string;
  priceUsd?: number;
  decimals?: number;
  minShieldAmount?: string;
}
```

### FeeRates

```typescript theme={null}
interface FeeRates {
  transferFeeFlat: string;   // flat fee in wei
  unshieldFeeBps: number;    // basis points
}
```

### Transaction / TransactionNote / TransactionsResult

```typescript theme={null}
interface TransactionNote {
  value: string;
  direction: string;          // "incoming" | "outgoing"
  isChange: boolean;
  leafIndex?: bigint;
  nullifier?: string;
  counterparty?: string;
  counterpartyType?: string;
}

interface Transaction {
  txHash: string;
  txType: string;             // "shield" | "unshield" | "transfer"
  direction: string;
  value: string;
  tokenId: bigint;
  createdAt: bigint;
  counterparty?: string;
  counterpartyType?: string;
  notes: TransactionNote[];
}

interface TransactionsResult {
  data: Transaction[];
  limit: number;
  next?: string;              // cursor for next page
}
```

### UnspentNote

```typescript theme={null}
interface UnspentNote {
  commitment: string;
  value: string;
  tokenAddress: string;
  tokenId: string;
  random: string;
  owner: string;
  spent: boolean;
  isOpaque: boolean;
  createdAt: bigint;
  leafIndex?: bigint;
  treeNumber?: bigint;
}
```

### MerkleTreeStats

```typescript theme={null}
interface MerkleTreeStats { size: string; root: string; }
```

### Audit result types

```typescript theme={null}
interface AuditTransactionEntry { /* ...tx_hash, tx_type, value_in/out, ... */ }
interface AuditNoteEntry        { /* ...commitment, owner, value, spent, ... */ }
interface AuditBalanceEntry     { /* ...pub_key, token, balance, tx_count, ... */ }

interface AuditTransactionsResult { transactions: AuditTransactionEntry[]; total: bigint; limit: number; offset: number; }
interface AuditNotesResult        { notes: AuditNoteEntry[];        total: bigint; limit: number; offset: number; }
interface AuditBalancesResult     { balances: AuditBalanceEntry[];  total: bigint; limit: number; offset: number; }
```

See the generated bindings for full field lists; they're stable but verbose.

### PendingTransaction

```typescript theme={null}
enum PendingTransactionType      { Shield = 'Shield', Unshield = 'Unshield', Transfer = 'Transfer' }
enum PendingTransactionStatus    { Pending = 'Pending', Preconfirmed = 'Preconfirmed', Completed = 'Completed', Failed = 'Failed', Blocked = 'Blocked' }
enum PendingTransactionDirection { Incoming = 'Incoming', Outgoing = 'Outgoing' }

interface PendingTransaction {
  txHash: string;
  txType: PendingTransactionType;
  status: PendingTransactionStatus;
  direction: PendingTransactionDirection;
  error?: string;
  tokenAddress?: string;
  amount?: string;
  from?: string;
  to?: string;
  receivers: PendingReceiverTransfer[];
  createdAt: bigint;
  updatedAt: bigint;
  tokenSymbol?: string;
  commitment?: string;
  requestId?: string;
  isChange: boolean;
}
```

### ExportedSession

```typescript theme={null}
interface ExportedSession {
  version: number;
  data: string;
}
```

`data` is an opaque serialized core session. Store and pass it back unchanged;
do not parse or persist individual key fields.

### IdentityResult

```typescript theme={null}
interface IdentityResult {
  mpk: string;
  viewingPublicKeyX: string;
  viewingPublicKeyY: string;
  privacyAddress: string;
}
```

### AppInfoEntry

```typescript theme={null}
interface AppInfoEntry {
  appId: string;
  name: string;
  description?: string;
}
```

***

## SdkError

Tagged union. Every variant is a constructable class, checked via
`.instanceOf(err)`. See the [Error Handling guide](./guides/error-handling)
for patterns and the full variant table.

```typescript theme={null}
SdkError.NotConnected.instanceOf(err)
SdkError.NotAuthenticated.instanceOf(err)
SdkError.AuthenticationFailed.instanceOf(err)
SdkError.InvalidConfig.instanceOf(err)
SdkError.ConfigError.instanceOf(err)
SdkError.NetworkError.instanceOf(err)
SdkError.WalletError.instanceOf(err)
SdkError.SignatureRejected.instanceOf(err)
SdkError.InsufficientBalance.instanceOf(err)
SdkError.InvalidAddress.instanceOf(err)
SdkError.InvalidAmount.instanceOf(err)
SdkError.InvalidInput.instanceOf(err)
SdkError.SerializationError.instanceOf(err)
SdkError.AuthServerError.instanceOf(err)
SdkError.ShieldError.instanceOf(err)
SdkError.TransferError.instanceOf(err)
SdkError.NoteError.instanceOf(err)
SdkError.MerkleError.instanceOf(err)
SdkError.ApiError.instanceOf(err)
SdkError.RateLimited.instanceOf(err)
SdkError.Forbidden.instanceOf(err)
SdkError.ResourceNotFound.instanceOf(err)
SdkError.WaitTimeout.instanceOf(err)
SdkError.TransactionFailed.instanceOf(err)
SdkError.InternalError.instanceOf(err)
SdkError.TransactionReverted.instanceOf(err)
SdkError.CryptoError.instanceOf(err)
SdkError.StateError.instanceOf(err)
SdkError.OperationError.instanceOf(err)
```

The string tag is also available at runtime via `SdkError_Tags`:

```typescript theme={null}
if (err.tag === SdkError_Tags.NotConnected) { ... }
```

***

## Gift Methods

Claimable transfers (gifts) — instance methods on `sdk`, taking **positional**
arguments. See the
[Claimable Transfers guide](./guides/claimable-transfers) and the
[concept page](/sdk/concepts/claimable-transfers).

<Info>
  **Preview feature — pending external audit, and enabled per deployment.** These
  methods may not be present in the checked-in generated bindings.
</Info>

Each fund/claim/refund method returns a `TransferResult` whose `giftRecord` and
`claimLink` fields are populated for gift operations.

```typescript theme={null}
sdk.giftFundToWallet(
  tokenAddress: string,
  amount: string,
  recipientWallet: string,
  refundAfterBlock: number,
  currentBlock: number,
): Promise<TransferResult>
```

Fund a gift bound to an Ethereum wallet address that may not be registered with
Privacy Boost. `amount` is wei; `refundAfterBlock`/`currentBlock` are block
numbers. Returns a `TransferResult` with `claimLink` and `giftRecord` populated.

```typescript theme={null}
sdk.giftFund(
  tokenAddress: string,
  amount: string,
  recipientPrivacyAddress: string,   // 194-char privacy address (ECDH target)
  recipientWallet: string,
  refundAfterBlock: number,
  currentBlock: number,
): Promise<TransferResult>
```

Fund a gift when the recipient is already a Privacy Boost user, sealing the
ciphertext to their viewing key. The third argument is the 194-char privacy
address.

```typescript theme={null}
sdk.giftClaim(index: number, acknowledgeUnknownSender: boolean): Promise<TransferResult>
```

Claim a pending gift by its position in `getPendingGifts()`.
`acknowledgeUnknownSender` must be `true` — it acknowledges accepting funds from
an unknown sender.

```typescript theme={null}
sdk.giftClaimByCGift(cGift: string, acknowledgeUnknownSender: boolean): Promise<TransferResult>
```

Claim a pending gift by its stable commitment `cGift` (preferred when the list
may shift as gifts settle).

```typescript theme={null}
sdk.giftClaimFromLink(link: string, acknowledgeUnknownSender: boolean): Promise<TransferResult>
```

Claim a gift directly from a `pbgift:v1:...` claim link, without a server lookup
first.

```typescript theme={null}
sdk.giftRefundByRecord(index: number): Promise<TransferResult>
```

Refund an unclaimed gift after its deadline, using a local gift record. `index`
is the positional index into `getGiftRecords()`.

```typescript theme={null}
sdk.giftRefund(
  recipientWallet: string,
  blind: string,
  refundAfterBlock: number,
  tokenId: number,
  amount: string,
  fundingTreeNumber: number,
  giftLeafIndex: number,
): Promise<TransferResult>
```

Refund an unclaimed gift by supplying every field manually — the fallback when
the local gift record is unavailable.

```typescript theme={null}
sdk.getPendingGifts(): Promise<PendingGift[]>
```

List the pending gifts addressed to the authenticated wallet.

```typescript theme={null}
sdk.getGiftRecords(): GiftRecord[]
```

Return the local records the SDK persisted for gifts you funded. These make a
gift refundable and travel inside an exported session. Synchronous.

```typescript theme={null}
sdk.decodeGiftLink(link: string): GiftLinkPreview     // throws
```

Decode a claim link into a preview offline, with no network call. Synchronous.

<Info>
  A third funding mode, `giftFundSecretBearer`, binds a gift to a secret instead
  of a wallet. It is **experimental, disabled by default, and a bearer
  instrument** (whoever holds the link can claim). See the
  [concept page](/sdk/concepts/claimable-transfers) before considering it.
</Info>

### GiftRecord

```typescript theme={null}
interface GiftRecord {
  recipientWallet: string;
  blind: string;
  refundAfterBlock: number;
  tokenId: number;
  amount: string;
  cGift: string;
  giftNpk: string;
  requestId: string;
  fundingTreeNumber?: number;
  giftLeafIndex?: number;
  status?: string;
}
```

### PendingGift

```typescript theme={null}
interface PendingGift {
  index: number;
  treeNumber: number;
  leafIndex: number;
  cGift: string;
  tokenId: number;
  amount: string;
  refundAfterBlock: number;
  recipientWallet: string;
}
```

### GiftLinkPreview

```typescript theme={null}
interface GiftLinkPreview {
  server: string;
  chainId: number;
  cGift: string;
  recipientWallet: string;
  tokenId: number;
  amount: string;
  refundAfterBlock: number;
}
```

The gift fields (`giftRecord`, `claimLink`) on `TransferResult` are populated only
for gift operations; see [UnshieldResult / TransferResult](#unshieldresult--transferresult).

***

## Portal

Portal deposit addresses. See the
[Portal Deposits guide](./guides/portal-deposits) and the
[concept page](/sdk/concepts/portal-deposits).

<Info>
  **Preview feature — pending external audit, and enabled per deployment.** React
  Native exposes portal lifecycle methods on `PrivacyBoost`. Low-level portal
  functions are limited to custodial escape hatches.
</Info>

The supported path is `sdk.createPortal(...)`, which derives the portal EOA from
the account seed and keeps the key inside core.

```typescript theme={null}
sdk.createPortal(index?: number): Promise<Portal>
```

Derive portal `E`, gaslessly delegate and register it via the server relays, then
publish the discovery entry. Omit `index` to use the next free derivation index.

```typescript theme={null}
sdk.listPortals(): Promise<PortalInfo[]>
```

List the authenticated account's portals with status and derivation index.

```typescript theme={null}
sdk.listPortalDeposits(portal: string): Promise<PortalDeposit[]>
```

List deposits observed at `portal`.

```typescript theme={null}
sdk.getPortalStatus(portal: string): Promise<PortalStatus>
```

Return registry/on-chain status for one portal.

```typescript theme={null}
sdk.sweepPortal(portal: string, tokenId: number): Promise<string>
```

Send `requestPortalDeposit` from the connected wallet and return the transaction
hash.

```typescript theme={null}
sdk.reclaimPortalDeposit(depositId: string): Promise<string>
```

Send `cancelPortalDeposit` from the connected wallet and return the transaction
hash.

```typescript theme={null}
sdk.withdrawPortal(
  index: number,
  token: string,
  to: string,
  amount: string,
  nonce: bigint,
  gasLimit: bigint,
  maxFeePerGas: string,
  maxPriorityFeePerGas: string,
): string
```

Build a signed EIP-1559 transaction that withdraws raw funds resting at the
seed-derived portal `E`. Broadcast the returned raw transaction yourself.

### Low-level escape hatches

These module-level functions are imported from
`@sunnyside-io/privacy-boost-react-native` and are for custodial integrations
that manage their own portal EOA key. The seed-derived `createPortal` flow does
not expose a private key.

```typescript theme={null}
generatePortalEoa(): PortalEoa
```

Generate a fresh portal EOA `E` and its secret private key.

```typescript theme={null}
encodePortalWithdraw(token: string, to: string, amount: string): string
```

Encode raw withdraw calldata for a custodial integration that already controls
its own portal EOA.

```typescript theme={null}
sdk.publishPortalRegistry(portal: string): Promise<void>
```

Publish the discovery registry entry (`E → blind`) — the supported submit path so
the indexer can credit deposits to the right account.

```typescript theme={null}
sdk.portalDelegateAddress(): string | undefined
```

Return the portal delegate address advertised by the server's `/info`, or
`undefined` if the server does not support portals.

### PortalEoa

```typescript theme={null}
interface Portal {
  address: string;
  index: number;
  bindH: string;
}

interface PortalInfo {
  address: string;
  index?: number;
  status: PortalStatus;
}

interface PortalStatus {
  registered: boolean;
  delegated: boolean;
  published: boolean;
}

enum PortalDepositState {
  PendingSweep = 'PendingSweep',
  Credited = 'Credited',
  Cancellable = 'Cancellable',
  Cancelled = 'Cancelled',
  Unknown = 'Unknown',
}

interface PortalDeposit {
  portalDepositId: string;
  portal: string;
  tokenId: number;
  grossAmount: string;
  netAmount: string;
  state: PortalDepositState;
  requestBlock: bigint;
  cancellableAtBlock: bigint;
}

interface PortalEoa {
  privateKey: string; // SECRET — custody it; never persisted by the SDK
  address: string;    // the portal deposit address E
}
```
