Multi-Chain
This guide covers usingChainContextHandle to operate on multiple blockchains from a single Android SDK instance.
For an overview of multi-chain concepts, see Multi-Chain Concepts. The same identity keys and privacy address apply on every chain.
Setup
Initialize the parent SDK against your primary chain, then open a chain context for each additional chain:serverUrl and chainId are the only fields you have to give: an omitted contract address is discovered from that chain’s server, and timeoutMs defaults to the SDK-wide 30s. A contract address you do pass has to parse, so a typo fails rather than falling back to the server-advertised pool. createChainContext is synchronous and throws SDKError if serverUrl is empty or not an HTTPS URL. Every call returns a new handle with its own session, so create each one once and keep it, for example in the repository or ViewModel that owns sdk.
Authentication
Each chain context authenticates before it can operate. Authentication reuses the parent SDK’s privacy keys but obtains a chain-specific JWT and registration, so the user signs once per chain. The calls below are suspend functions; run them inside a coroutine:ChainContextHandle.authenticate(wallet) takes only a WalletDelegate; the key source and token provider come from the parent SDK. Apps that authenticate through an external identity provider pass that provider’s token as externalToken.
Operations
Once authenticated, aChainContextHandle exposes the same per-chain operations as the parent SDK.
Deposits
Private Transfers
Withdrawals
Balances
Status Polling and History
What the Handle Carries
A handle covers the operations whose state is per chain:shield, prepareShield, unshield, send and sendBatch, unwrapWeth, consolidateNotes, balances and the token catalog, fees, status polling, history and unspent notes, pending-transaction tracking (including waitForPreconfirmation and waitForFinality), and the claimable-transfer (gift) methods.
It does not carry portal deposits, earn and swap, audit, or the private treasury (contacts and labels). Those stay on the parent PrivacyBoost, as do resolveIdentity, parseAmount, formatAmount, address validation, setChainReader, and session export. The parent’s pending transactions and token registry reflect its own chain only, so read each chain’s pending transactions and balances through that chain’s handle rather than the parent.
The handle has no vault of its own: it shares the parent’s resident keys, so lock() and the auto-lock timers on the parent apply to it as well. Its JWT is separate, which is why clearSession() on the parent does not reach it.