Skip to main content

API Reference

Complete API reference for the Privacy Boost Android SDK.

Generated Documentation

Full API documentation can be generated using cargo doc:

PrivacyBoost

Main SDK class for Android.

Constructor

Creates a new SDK instance. Parameters:
  • config - SDK configuration

Properties

Connection & Authentication Methods

authenticate

Connect a wallet, derive privacy keys, and authenticate with the Privacy Boost backend in a single call. Parameters:
  • wallet - Implementation of WalletDelegate interface
  • keySource - Optional key derivation source. If null and no persistence is configured, defaults to KeySource.WalletDerived. If null with persistence configured and no existing vault, an error is thrown.
  • tokenProvider - Optional custom token provider. If null, the SDK sends the login payload directly to the Privacy Boost backend. Supply a TokenProvider to route authentication through your own server.
Returns: AuthResult - see AuthResult for all possible outcomes. Throws:
  • SDKError.WalletError if signing fails
  • SDKError.InvalidConfig if configuration is invalid or keySource is required but missing
  • SDKError.NetworkError if backend unreachable

submitCredential

Submit a credential when authenticate() returns CredentialRequired. Parameters:
  • credential - The credential string
  • tokenProvider - Optional custom token provider for routing authentication through your own server
Returns: LoginResult with privacy address and MPK

logout

End session completely, clear all state.

clearSession

Clear JWT only, keep keys for quick re-auth.

lock

Zeroize all resident key material and drop the session JWT, keeping the persisted encrypted vault so the user can unlock again without re-deriving keys. The next key access throws SDKError.NotAuthenticated; call authenticate again to reopen the vault. The idle and absolute timers in PrivacyBoostConfig invoke the same lock automatically. Chain-context handles created from this instance share the wiped keys but keep their own JWT, so call clearSession() on each of them separately.

State Accessors

Balance Methods

getBalance

Get balance for a specific token. Parameters:
  • tokenAddress - ERC-20 token contract address
Returns: TokenBalance with shielded and wallet amounts

getAllBalances

Get all token balances.

Fee Methods

getFees

Returns the ordinary transfer and unshield fee quote for a token.

getGatewayFees

Returns the Gateway fee that replaces the ordinary unshield fee. Pass the first four calldata bytes as gatewaySelector to resolve a selector-specific override, or null for the Gateway-wide default.

Vault Operations

deposit

Deposit tokens into the shielded pool. Parameters:
  • tokenAddress - Token contract address
  • amount - Amount in wei (as string)
Returns: ShieldResult with transaction hash

withdraw

Withdraw tokens from the shielded pool. Parameters:
  • tokenAddress - Token contract address
  • amount - Amount in wei (as string)
  • recipient - Recipient Ethereum address
Returns: UnshieldResult with transaction hash

send

Send a private transfer. Parameters:
  • tokenAddress - Token contract address
  • amount - Amount in wei (as string)
  • recipientPrivacyAddress - Recipient’s 194-char privacy address
Returns: TransferResult with transaction hash

sendBatch

Send one private transfer paying several recipients: one request, one fee, one set of input notes. Parameters:
  • tokenAddress - Token contract address
  • recipients - TransferRecipient(recipient, amount) entries in output order, at least one
Shape limits: the transfer’s output count is the recipient count plus a change note, and the server only proves specific (inputs, outputs) combinations, so a longer recipient list limits how many input notes can be spent — past two recipients, at most four. Requests no enabled circuit can serve fail with UNSUPPORTED_TRANSFER_SHAPE before submission. Returns: TransferResult with transaction hash

prepareShield

Build 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). Returns the calldata to relay plus the note commitment; nothing is sent on-chain and no wallet is used. After relaying, pass the mined receipt to the top-level finalizeShield(...) to recover the on-chain request id. Parameters:
  • tokenAddress - Token contract address (zero address = native ETH)
  • amount - Amount in wei (as string)
  • recipient - (Optional) recipient privacy address. Pass null to shield to yourself.
Returns: PreparedShield with the calls to relay and the note commitment

Earn and Gateway

Gateway earn operations deposit into or redeem from a yield vault from inside the pool. The catalog and history reads are public and work before login; earnDeposit and earnRedeem need an authenticated session and a ChainReaderDelegate registered with setChainReader. All of these are suspend functions; call them inside withContext(Dispatchers.IO).

earnDeposit / earnRedeem

For a deposit, amount is the net amount that enters the vault; the unshield fee is charged on top. For a redeem, amount is the share amount. slippageBps of null uses the gateway default.

listEarnVaults / getEarnVault

The catalog with typed vault summaries and gateway-wide availability, or one vault with its detail fields. Check availability.deposit.canSubmit on a summary before offering a deposit; retryable says whether a closed window is expected to reopen on its own.

getGatewayConfig

Gateway discovery configuration: executor address, adapters, request constraints, rescue delay, policy, and current availability.

getEarnVaultHistory / getEarnVaultCharts

One cached series (metric is EarnHistoryMetric.TVL_USD or NET_APY) or both series fetched together. period is ONE_WEEK, ONE_MONTH, THREE_MONTHS, or ALL; null uses the server default. The selectors are enums here and wire strings on the *Json accessors, which keep the signatures they shipped with. APY values are fractions (0.05 is 5%), a null point value is an upstream gap, and metadata.state reports freshness. A cold cache can briefly fail with a retryable error. The listEarnVaultsJson, getGatewayConfigJson, getEarnVaultHistoryJson, and getEarnVaultChartsJson methods return the same data as canonical JSON strings for callers that parse the wire shape themselves.

Transaction History

Get transaction history. Parameters:
  • txType - Filter by type: “deposit”, “withdraw”, “transfer”
  • tokenAddress - Filter by token
  • limit - Maximum results

queryTransactionHistory

History under the full query: type, token id and direction filters, page size and cursor, and whether each Gateway operation’s two rows are folded into one. Use it for any filter getTransactionHistory does not take. null fields are unfiltered. Suspend, so call it inside withContext(Dispatchers.IO). Parameters: Returns: TransactionsResult with the page of transactions and the cursor for the next page

Session Persistence

exportSession

Export session data for persistence. Returns: ExportedSession or null if not authenticated

importSession

Import a previously exported session. Returns: true if session is valid and imported

Private Treasury

Per-wallet contacts and transaction labels, stored encrypted on the server and readable only with the session’s keys. All methods are suspend functions (call them inside withContext(Dispatchers.IO)), throw SDKError, and require an authenticated session. A row whose decryptionFailed is true is one the server could no longer open: show it as unreadable, not as missing.

listContacts

Page through the wallet’s contacts. Both arguments default, so listContacts() is the first page at the server’s page size; pass the previous page’s nextCursor after that.

createContact

Create one contact. privacyAddress and nickname are required and come first; everything after them is defaulted, including clientId, a caller-chosen correlation id that bulk results echo back.

bulkCreateContacts

Create several contacts in one request. A contact whose privacy address already exists is reported under skipped with the existing row’s id rather than failing the batch.

updateContact

Patch one contact. Every field is a patch value (StringPatch.Keep, StringPatch.Clear, or StringPatch.Set(value), and the MetadataPatch equivalents), so “leave alone” is always Keep and never a null that could be read as a clear. nickname and emoji are the two the API can only replace: Clear on either throws SdkError.InvalidInput naming the field rather than being silently downgraded to Keep.

deleteContact

listLabels

Page through the wallet’s transaction labels, using cursor the same way as listContacts.

upsertLabel

Create or replace the label on a transaction hash. The whole label is replaced, so an absent field means “no value”.

deleteLabel

Campaigns

getStartaleCampaignProgress

Lifetime Startale mission progress for the authenticated user and app. The deposit mission is priced at query time, so it is not monotonic: record the first true your app sees and never downgrade it. campaignTokenId is null only when no campaign token is configured, in which case every shielded token counted toward the deposit total. Suspend, so call it inside withContext(Dispatchers.IO).

Address Lookup

resolveIdentity

Look up a user’s privacy address by MPK or Ethereum address. Parameters:
  • identifier - MPK or Ethereum address
Returns: IdentityResult with privacy address and public keys

Chain Context

createChainContext

Open a handle for a second chain that shares this instance’s identity keys and wallet but has its own server, JWT, and chain state. Authenticate it separately with authenticate(wallet), and clear it separately with clearSession(); lock() on the parent wipes the shared keys but leaves the handle’s JWT in place. Synchronous; throws SDKError if serverUrl is empty or not an HTTPS URL, or if a contract address is present but malformed. Every call returns a new handle, so create each one once and keep it. Parameters: Returns: ChainContextHandle See the Multi-Chain guide for setup and cross-chain patterns.

Utilities


ChainContextHandle

Returned by createChainContext(config). A chain-scoped facade over one PrivacyBoost identity: it carries the operations whose state is per chain and shares the parent’s keys, so the wallet signs once per chain to obtain that chain’s JWT. Portal deposits, earn and swap, audit, and the private treasury stay on the parent instance, as do resolveIdentity, the amount utilities, setChainReader, and session export. Methods that return a network result are suspend functions; call them inside withContext(Dispatchers.IO).
The claimable-transfer methods (giftFund, giftFundToWallet, giftFundSecretBearer, giftClaim, giftClaimByCGift, giftClaimFromLink, giftRefund, giftRefundByRecord, getPendingGifts, getGiftRecords, decodeGiftLink) have the same signatures as on PrivacyBoost; see Gift Methods. The handle adds importGiftRecords(records: List<GiftRecord>), which rehydrates its sender ledger from persisted records so unclaimed gifts stay refundable through giftRefundByRecord across restarts. authenticate(wallet, externalToken) takes only the wallet delegate; the key source and token provider come from the parent. externalToken carries an external identity provider’s token on this chain’s login and defaults to null.

Module Functions

  • sdkVersion() — Returns the SDK version string
  • generateMnemonic() — Generates a random 12-word BIP-39 mnemonic
  • registerKeychainDelegate(delegate, service): registers the app’s Keystore implementation for StorageBackend.OS_KEYCHAIN persistence. Process-wide; call it once, before constructing a PrivacyBoost whose config selects OS_KEYCHAIN, or construction throws, and a later call replaces the delegate for every instance. service namespaces the stored items; null uses the SDK’s own name, and an app running two SDK instances should pass its own. PrivacyBoostDefaults.create(context, config) in com.privacyboost.defaults registers DefaultKeystoreDelegate(context) for you. See KeychainDelegate Interface.
  • hasKeychainDelegate(): whether a delegate is registered

Stateless shield helpers

Top-level functions 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.
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.

Types

PrivacyBoostConfig

Set approvalOnly to true for approval-only EOA accounts. The SDK discovers the chain-specific AuthRegistry from the configured server. persistenceStorage = StorageBackend.OS_KEYCHAIN requires a KeychainDelegate registered with registerKeychainDelegate (or through PrivacyBoostDefaults.create) before construction; LOCAL_STORAGE and INDEXED_DB are browser backends and are rejected. persistenceUnlock may be NONE, PIN, PASSWORD, or BIOMETRIC; PASSKEY is rejected. idleTtlSecs and absoluteTtlSecs drive auto-lock, in seconds: the first is how long the resident keys may go unused, the second how long after an unlock they may stay resident at all. null or 0u disables the respective timer. Both are checked lazily, on the next key access: once one has elapsed, that access zeroizes the keys and throws SDKError.NotAuthenticated, exactly as lock() would, and the persisted vault is kept so authenticate can reopen it. They bound key use rather than key residency; call lock() from your own timer when the keys must be gone at a fixed time. See Auto-lock. Both fields default to null, so existing constructor calls keep compiling.

ChainContextConfig

Per-chain configuration for createChainContext. chainId and timeoutMs (request timeout in milliseconds) are required; the optional fields are discovered from that chain’s server when null. A contract address you do pass has to parse — a malformed one is rejected rather than dropped, so a typo can never fall back to the server-advertised pool.

KeySource

Specifies how privacy keys are derived. Passed as an optional parameter to authenticate().
  • WalletDerived - Derive keys from a deterministic wallet signature (default when no persistence configured)
  • Mnemonic - Derive keys from a BIP-39 mnemonic phrase
  • RawSeed - Derive keys from raw hex entropy (for testing)

AuthResult

AccountCreationRequired contains the account ID, canonical account salt, and a prepared EOA transaction (chainId, to, value, data). The SDK validates the target against the AuthRegistry advertised by this deployment’s /api/v1/info.

LoginResult

TokenBalance

FeeRates

Gateway fields are populated only by getGatewayFees. gatewayFeeBase is flat, unshield_amount, or zero and identifies the amount used for fee calculation.

ShieldResult

Returned by shield and finalizeShield.

UnshieldResult

TransferResult

Call

A single on-chain call to relay. value and data are 0x-hex.

PreparedShield

Returned by prepareShield and buildShieldPayload.

TransactionReceipt

The mined-receipt type passed to finalizeShield.

Transaction

TransactionsResult

One page of history, returned by getTransactionHistory, getCollapsedTransactionHistory, and queryTransactionHistory.

TransactionHistoryQuery

null fields are unfiltered. Every field is defaulted, so name only the filters you want: TransactionHistoryQuery(tokenId = 1u) is a valid query.

IdentityResult

ExportedSession

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

Private Treasury Types

Earn and Gateway Types

StartaleCampaignProgress


WalletDelegate Interface


TokenProvider Interface

Implement this interface to route authentication through your own server. The SDK serializes the login payload as a JSON string and passes it to getToken(). Your implementation should forward this payload to your backend, which adds its own credentials and calls the Privacy Boost API.

TokenResponse

Example


KeychainDelegate Interface

Serves persistenceStorage = StorageBackend.OS_KEYCHAIN. Register an implementation process-wide with registerKeychainDelegate before constructing the SDK, or let PrivacyBoostDefaults.create(context, config) register DefaultKeystoreDelegate(context). Values are opaque bytes; requireBiometry is true when the config selects UnlockMethod.BIOMETRIC, and the item must then be stored under a Keystore key that requires a class-3 biometric. The default delegate expects the app to complete its own BiometricPrompt before the SDK reads or writes such an item. See Session Storage.

SDKError


Gift Methods

Claimable-transfer (gift) methods on the PrivacyBoost instance. See the Claimable Transfers guide for usage and the concept page for the trust model. Suspend methods should be called inside withContext(Dispatchers.IO).

giftFundToWallet

Fund a gift bound to a recipient wallet address that may not be registered yet. Parameters:
  • tokenAddress - Token contract address
  • amount - Amount in wei (as string)
  • recipientWallet - Recipient’s Ethereum address the gift binds to (irrevocable)
  • refundAfterBlock - Block height after which an unclaimed gift may be reclaimed
  • currentBlock - Current chain head; pre-validates the refund delay
Returns: TransferResult with giftRecord (persist it) and claimLink

giftFund

Fund a gift when the recipient is already a Privacy Boost user. Seals the gift ciphertext to their viewing key for the smoothest discovery. Parameters:
  • tokenAddress - Token contract address
  • amount - Amount in wei (as string)
  • recipientPrivacyAddress - Recipient’s 194-char privacy address (ECDH target)
  • recipientWallet - Recipient’s Ethereum address the gift binds to (irrevocable)
  • refundAfterBlock - Block height after which an unclaimed gift may be reclaimed
  • currentBlock - Current chain head; pre-validates the refund delay
Returns: TransferResult with giftRecord (persist it) and claimLink

giftClaim

Claim a pending gift by its position in getPendingGifts(). Parameters:
  • index - Position in the pending-gift list
  • acknowledgeUnknownSender - Must be true; consents to funds from a hidden sender

giftClaimByCGift

Claim a pending gift by its stable commitment cGift. Preferred over index when the pending list may shift as gifts settle. Parameters:
  • cGift - Stable gift commitment
  • acknowledgeUnknownSender - Must be true
Claim directly from a pbgift:v1:... claim link without a server lookup first. Parameters:
  • link - A pbgift:v1:... claim link
  • acknowledgeUnknownSender - Must be true

giftRefundByRecord

Refund an unclaimed gift using the local gift record saved at funding time. Only valid after refundAfterBlock has elapsed. Parameters:
  • index - Position in getGiftRecords()

giftRefund

Refund an unclaimed gift by supplying every field manually — the fallback when the local gift record has been lost.

getPendingGifts

List pending gifts addressed to the authenticated wallet (TEE discovery).

getGiftRecords

List the local gift records the SDK persisted for gifts you funded. These are what make an unclaimed gift refundable and are included in an exported session.
Decode a pbgift:v1:... claim link into a preview. Synchronous and throwing — works fully offline, so it does not need withContext(Dispatchers.IO). Parameters:
  • link - A pbgift:v1:... claim link
Returns: GiftLinkPreview
giftFundSecretBearer(...) also exists. It is a bearer instrument (whoever holds the link can claim), selected only by that explicit method. See the concept page before considering it.

Gift Types

The gift fields are added to the existing TransferResult returned by the fund / claim / refund methods:

Portal

Portal deposit addresses. Android exposes the portal lifecycle as methods on PrivacyBoost — createPortal owns the EIP-7702 delegation and the gasless registration for you. Low-level portal functions are limited to custodial escape hatches. See the Portal Deposits guide for the lifecycle and the concept page for the trust model and current limitations.

Instance Methods

publishPortalRegistry

Publish the private discovery registry entry so the indexer can credit deposits to the owner’s account. Suspend — call inside withContext(Dispatchers.IO). Parameters:
  • portal - The portal deposit address E
  • index - The seed-derivation index of portal

portalDelegateAddress

Returns the portal delegate address advertised by the server’s /info, or null if the server does not support portals.

Portal lifecycle

  • createPortal(index) — Derive portal E, gaslessly delegate and register it via the server relays, then publish the discovery entry. Pass null to use the next free derivation index.
  • listPortalsPage(cursor, limit) — One page of the authenticated account’s portals with status and derivation index. limit must be between 1 and 100; pass the page’s nextCursor back as cursor to continue, and treat an absent nextCursor as the final page.
  • listPortalDepositsPage(portal, cursor, limit) — One page of the deposits observed at a portal. Same cursor and limit semantics.
  • getPortalStatus(portal) — Return registry/on-chain status for one portal.
  • sweepPortal(portal, tokenId) — Send requestPortalDeposit from the connected wallet and return the transaction hash.
  • reclaimPortalDeposit(depositId) — Send cancelPortalDeposit from the connected wallet and return the transaction hash.
  • withdrawPortal(...) — Build a signed EIP-1559 transaction that withdraws raw funds resting at seed-derived portal E. Broadcast the returned raw transaction yourself.

Top-Level Functions

These package-level functions are low-level escape hatches for custodial integrations that manage their own portal EOA key. The seed-derived createPortal flow does not expose a private key.
  • generatePortalEoa() — Generate a fresh portal address E and its secret private key for custodial integrations.
  • encodePortalWithdraw(token, to, amount) — Encode PortalDelegate.withdraw calldata for a custodial integration that already controls E.

Portal Types


Deposit Cancellation

shield(...) moves the depositor’s tokens into the pool and holds them there until the sequencer settles the request into the note tree. Almost always that happens within a couple of blocks. When it doesn’t, because of a commitment mismatch, a malformed ciphertext, or a stalled sequencer, the tokens stay in escrow and the depositor reclaims them by cancelling the request on-chain. The server will tell you a shield failed — getShieldStatus(requestId) returns failed for a commitment mismatch or a malformed ciphertext — but it says nothing about the escrow behind it: whether the pool still holds it, who may reclaim it, and when. A stalled sequencer doesn’t even produce that failed row. So use getShieldStatus to notice something went wrong, and these two methods to find out what you can do about it. They read the pool directly and tell you what it would do before you ask anyone to sign.
getDepositCancellation reads chain state, so it needs a ChainReaderDelegate registered with setChainReader. cancelDeposit works without one — it just skips its preflight. It’s the same optional delegate earn uses, and any RPC-connected wallet can back it.

Instance Methods

listShieldsByStatus

Find a depositRequestId you never kept. Lists the authenticated wallet’s own shield requests in the given public statuses (pending, processing, preconfirmed, completed, failed), oldest first. An empty list means the server’s default of pending. Pass failed to list the shields whose escrow may still be sitting in the pool, then feed each requestId to getDepositCancellation. Served by the server and scoped to the session, so it needs no ChainReaderDelegate and cannot enumerate anyone else’s deposits. failed is a public status the server folds several internal ones into, so it also covers shields rejected as below-minimum or blocked. A stalled sequencer produces no failed row at all — those stay pending. Returns: UnsettledShield per row: requestId, status, and the optional txHash, blockNumber, createdAt and error.

depositRequestIdsFromTransaction

The fallback when the app kept the shield’s transaction hash but not its request id. Reads the receipt and returns every DepositRequested id the pool emitted, in log order — more than one when an aggregating relayer settled several callers in the same transaction. Empty means the transaction emitted no DepositRequested from the configured pool, which is the answer for a hash that was never a shield rather than an error, so candidate hashes can be swept. Reads the chain, so it needs the same ChainReaderDelegate as getDepositCancellation.

getDepositCancellation

Read the pool and report whether cancelDeposit would succeed for the connected wallet right now, without sending anything. Costs three eth_calls plus one eth_blockNumber, and throws if no ChainReaderDelegate is set. Suspend, so call it inside withContext(Dispatchers.IO). Parameters:
  • depositRequestId - The DepositRequested event’s indexed topic1, a uint256. It’s the same value shield(...) and finalizeShield(...) return as ShieldResult.requestId. Decimal or 0x-hex; the result normalizes it to decimal.
Returns: DepositCancellation with the escrowed amount, the block the delay expires at, and a reason you can show the user directly

cancelDeposit

Send cancelDeposit from the connected wallet and return the transaction hash. The full escrowed amount goes back to the depositor. Suspend, so call it inside withContext(Dispatchers.IO). The call preflights through getDepositCancellation and throws locally, before anything is signed, when the pool would revert. The thrown message is the status reason, so a stuck deposit explains itself instead of burning gas on an opaque revert. Without a ChainReaderDelegate there’s no preflight: the transaction is submitted anyway and the chain arbitrates. Parameters:
  • depositRequestId - Same id getDepositCancellation takes
Returns: Transaction hash

Who can cancel, and when

Only the address that submitted the deposit can cancel it, and the refund goes to that address. For a relayer-submitted shield that’s the relayer, not the note recipient, so a user whose deposit is genuinely theirs can still get NotDepositor back. The cancel delay is measured in blocks and read from the pool’s cancelDelay(). Read the deployed value instead of hardcoding a delay, using cancelDelay, cancellableAtBlock, and blocksRemaining from the returned status.

Cancellation states

state mirrors the reverts in the pool’s cancelDeposit, reported permanent-blocker first rather than in the pool’s own check order. The pool checks the depositor before anything else, and that check would mask the two conditions no caller can clear. A gateway-origin deposit stores the gateway contract as its depositor, never the wallet whose funds routed through it, so it reports GatewayOrigin for every caller and at every point in the delay window. Waiting never makes it cancellable.

Deposit Cancellation Types

See Also