Skip to main content

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.

Android Quickstart

Integrate private token transfers into your Android app with the Kotlin SDK.
This quickstart gets you running in 5 minutes with minimal explanation. For detailed walkthroughs of each step, see the Android Getting Started guide. For background on configuration and auth options, see Setup.

Installation

Gradle

Add to your build.gradle.kts:
dependencies {
    implementation("io.privacy-boost:privacy-boost-android:1.0.0")
}
Or for Groovy (build.gradle):
dependencies {
    implementation 'io.privacy-boost:privacy-boost-android:1.0.0'
}

Quick Example

1. Create Wallet Delegate

import com.privacyboost.sdk.*

class MyWalletDelegate(private val wallet: YourWalletImplementation) : WalletDelegate {

    override suspend fun getAddress(): String {
        return wallet.address
    }

    override suspend fun getChainId(): ULong {
        return wallet.chainId.toULong()
    }

    override suspend fun signMessage(message: String): String {
        return wallet.sign(message)
    }

    override suspend fun signTypedData(typedDataJson: String): String {
        return wallet.signTypedData(typedDataJson)
    }

    override suspend fun sendTransaction(toAddress: String, value: String, data: String): String {
        return wallet.sendTransaction(toAddress, value, data)
    }

    override suspend fun waitForTransactionReceipt(txHash: String): TransactionReceipt {
        val receipt = wallet.waitForReceipt(txHash)
        return TransactionReceipt(
            txHash = txHash,
            status = receipt.status,
            logs = receipt.logs,
        )
    }
}

2. Initialize and Use SDK

import com.privacyboost.sdk.*
import kotlinx.coroutines.launch

// 1. Create configuration — server discovers chainId / contracts when null.
val config = PrivacyBoostConfig(
    serverUrl = "https://test-api.privacyboost.io",
    chainId = null,
    shieldContractAddress = null,
    wethContractAddress = "0x4200000000000000000000000000000000000006",
    teePublicKey = null,
    appId = "app_abc123xyz",
    persistenceStorage = null,
    persistenceUnlock = null,
)

// 2. Initialize SDK
val sdk = PrivacyBoost(config)

// 3. Authenticate — keySource defaults to WalletDerived when persistence is off.
lifecycleScope.launch {
    val walletDelegate = MyWalletDelegate(wallet)
    val authResult = sdk.authenticate(
        wallet = walletDelegate,
        keySource = null,
        tokenProvider = null,
    )
    when (authResult) {
        is AuthResult.Authenticated -> {
            println("Privacy address: ${authResult.loginResult.privacyAddress}")
        }
        is AuthResult.CredentialRequired -> {
            // Prompt the user for their PIN / password, then submit it.
            val pin = promptUserForPin(authResult.challenge)
            val loginResult = sdk.submitCredential(pin, tokenProvider = null)
            println("Privacy address: ${loginResult.privacyAddress}")
        }
        is AuthResult.MnemonicGenerated -> {
            // First-time user — show the mnemonic, confirm they saved it,
            // then proceed.
            confirmMnemonicSaved(authResult.mnemonic)
            val loginResult = sdk.proceedAfterMnemonic(
                credential = null,
                tokenProvider = null,
            )
            println("Privacy address: ${loginResult.privacyAddress}")
        }
        is AuthResult.RecoveryRequired -> {
            // Local keys are missing but an account exists — prompt for the
            // recovery mnemonic and re-authenticate with KeySource.Mnemonic.
            println("Recovery required: ${authResult.challenge}")
        }
    }
}
MnemonicGenerated fires for first-time users. CredentialRequired only fires when persistence with PIN / password / biometric unlock is configured. RecoveryRequired fires when the device has an account record but local keys are missing — prompt for the mnemonic and re-authenticate with KeySource.Mnemonic(phrase).
// 4. Check balance
val balance = sdk.getBalance("0x...")
println("Shielded: ${balance.shieldedBalance}")

// 5. Deposit
val shieldResult = sdk.shield(
    tokenAddress = "0x...",
    amount = "1000000000000000000" // 1 token (18 decimals)
)
println("Deposit tx: ${shieldResult.txHash}")

// 6. Transfer
val transferResult = sdk.send(
    tokenAddress = "0x...",
    amount = "500000000000000000", // 0.5 tokens
    recipientPrivacyAddress = recipientPrivacyAddress
)
println("Transfer tx: ${transferResult.txHash}")

// 7. Withdraw
val unshieldResult = sdk.unshield(
    tokenAddress = "0x...",
    amount = "250000000000000000", // 0.25 tokens
    recipient = "0x..."
)
println("Withdraw tx: ${unshieldResult.txHash}")

Jetpack Compose Example

import androidx.compose.runtime.*
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.privacyboost.sdk.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class WalletViewModel : ViewModel() {
    private val _isAuthenticated = MutableStateFlow(false)
    val isAuthenticated: StateFlow<Boolean> = _isAuthenticated

    private val _privacyAddress = MutableStateFlow<String?>(null)
    val privacyAddress: StateFlow<String?> = _privacyAddress

    private var sdk: PrivacyBoost? = null

    fun authenticate(wallet: WalletDelegate) {
        viewModelScope.launch {
            try {
                val config = PrivacyBoostConfig(/* ... */)
                sdk = PrivacyBoost(config)

                val result = sdk?.authenticate(
                    wallet = wallet,
                    keySource = null,
                    tokenProvider = null,
                )
                when (result) {
                    is AuthResult.Authenticated -> {
                        _privacyAddress.value = result.loginResult.privacyAddress
                        _isAuthenticated.value = true
                    }
                    is AuthResult.MnemonicGenerated,
                    is AuthResult.CredentialRequired,
                    is AuthResult.RecoveryRequired -> {
                        // Handle multi-step auth flows — see the Quick Example above.
                    }
                    null -> {}
                }
            } catch (e: Exception) {
                println("Authentication failed: ${e.message}")
            }
        }
    }

    fun deposit(tokenAddress: String, amount: String) {
        viewModelScope.launch {
            sdk?.shield(tokenAddress = tokenAddress, amount = amount)
        }
    }

    fun clearSession() {
        sdk?.clearSession()
        _isAuthenticated.value = false
        _privacyAddress.value = null
    }
}

@Composable
fun WalletScreen(viewModel: WalletViewModel = viewModel()) {
    val isAuthenticated by viewModel.isAuthenticated.collectAsState()
    val privacyAddress by viewModel.privacyAddress.collectAsState()

    Column {
        if (isAuthenticated) {
            Text("Privacy Address:")
            Text(privacyAddress ?: "", style = MaterialTheme.typography.caption)

            Button(onClick = {
                viewModel.deposit("0x...", "1000000000000000000")
            }) {
                Text("Deposit 1 Token")
            }

            Button(onClick = { viewModel.clearSession() }) {
                Text("Clear Session")
            }
        } else {
            Button(onClick = {
                viewModel.authenticate(MyWalletDelegate(wallet))
            }) {
                Text("Connect Wallet")
            }
        }
    }
}

Next Steps

Android Getting Started

Detailed walkthrough of each integration step

Setup Guide

App ID, configuration, and auth method selection

Wallet Integration

Detailed WalletDelegate implementation

Session Storage

Android Keystore storage and biometric unlock