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.

Transaction History

This guide covers querying and filtering transaction history in the Privacy Boost Android SDK.

Basic Usage

val transactions = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(
        txType = null,
        tokenAddress = null,
        limit = null
    )
}

for (tx in transactions) {
    println("${tx.txType}: ${tx.amount} - ${tx.txHash}")
}

Transaction Type

data class Transaction(
    val txHash: String,           // Transaction hash
    val txType: String,           // "deposit", "withdraw", or "transfer"
    val tokenAddress: String,     // Token contract address
    val amount: String,           // Amount in wei
    val direction: String,        // "incoming" or "outgoing"
    val senderPubKey: String,     // Sender's public key
    val receiverPubKeys: List<String>, // Receiver public keys
    val createdAt: ULong          // Unix timestamp
)

Filtering History

By Transaction Type

// Only deposits
val deposits = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(txType = "deposit", tokenAddress = null, limit = null)
}

// Only withdrawals
val withdrawals = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(txType = "withdraw", tokenAddress = null, limit = null)
}

// Only transfers
val transfers = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(txType = "transfer", tokenAddress = null, limit = null)
}

By Token

val usdcHistory = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(
        txType = null,
        tokenAddress = "0x...usdc-address",
        limit = null
    )
}

With Limit

// Get last 10 transactions
val recent = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(txType = null, tokenAddress = null, limit = 10u)
}

Combined Filters

// Last 5 USDC deposits
val recentUsdcDeposits = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(
        txType = "deposit",
        tokenAddress = "0x...usdc-address",
        limit = 5u
    )
}

Filter Parameters

ParameterTypeDescription
txTypeString?Filter by type: "deposit", "withdraw", "transfer"
tokenAddressString?Filter by token contract address
limitUInt?Maximum number of results

ViewModel Integration

class TransactionViewModel(private val sdk: PrivacyBoost) : ViewModel() {

    private val _transactions = MutableStateFlow<List<Transaction>>(emptyList())
    val transactions: StateFlow<List<Transaction>> = _transactions.asStateFlow()

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()

    private val _filter = MutableStateFlow("all")
    val filter: StateFlow<String> = _filter.asStateFlow()

    fun setFilter(type: String) {
        _filter.value = type
        loadTransactions()
    }

    fun loadTransactions() {
        viewModelScope.launch {
            _isLoading.value = true
            try {
                val typeFilter = if (_filter.value == "all") null else _filter.value
                val result = withContext(Dispatchers.IO) {
                    sdk.getTransactionHistory(
                        txType = typeFilter,
                        tokenAddress = null,
                        limit = 50u
                    )
                }
                _transactions.value = result
            } catch (e: SDKError) {
                println("Failed to load transactions: $e")
            }
            _isLoading.value = false
        }
    }
}

Displaying Transactions in Compose

@Composable
fun TransactionHistory(viewModel: TransactionViewModel) {
    val transactions by viewModel.transactions.collectAsState()
    val isLoading by viewModel.isLoading.collectAsState()
    val filter by viewModel.filter.collectAsState()

    val filters = listOf("all", "deposit", "withdraw", "transfer")

    LaunchedEffect(Unit) {
        viewModel.loadTransactions()
    }

    Column {
        // Filter tabs
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceEvenly
        ) {
            filters.forEach { type ->
                FilterChip(
                    selected = filter == type,
                    onClick = { viewModel.setFilter(type) },
                    label = { Text(type.replaceFirstChar { it.uppercase() }) }
                )
            }
        }

        // Transaction list
        if (isLoading) {
            CircularProgressIndicator(modifier = Modifier.align(Alignment.CenterHorizontally))
        } else if (transactions.isEmpty()) {
            Text("No transactions found", color = Color.Gray)
        } else {
            LazyColumn {
                items(transactions) { tx ->
                    TransactionRow(transaction = tx)
                }
            }
        }
    }
}

@Composable
fun TransactionRow(transaction: Transaction) {
    val icon = when (transaction.txType) {
        "deposit" -> Icons.Default.ArrowDownward
        "withdraw" -> Icons.Default.ArrowUpward
        "transfer" -> Icons.Default.SwapHoriz
        else -> Icons.Default.Circle
    }

    val dateFormatter = SimpleDateFormat("MMM d, yyyy HH:mm", Locale.getDefault())
    val formattedDate = dateFormatter.format(Date(transaction.createdAt.toLong() * 1000))

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Icon(imageVector = icon, contentDescription = transaction.txType)
        Spacer(modifier = Modifier.width(12.dp))
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text = transaction.txType.replaceFirstChar { it.uppercase() },
                style = MaterialTheme.typography.titleSmall
            )
            Text(
                text = formattedDate,
                style = MaterialTheme.typography.bodySmall,
                color = Color.Gray
            )
        }
        Text(
            text = transaction.amount,
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

Error Handling

try {
    val transactions = withContext(Dispatchers.IO) {
        sdk.getTransactionHistory(txType = null, tokenAddress = null, limit = null)
    }
} catch (e: SDKError) {
    when (e) {
        is SDKError.NotAuthenticated ->
            println("Please log in first")
        is SDKError.NetworkError ->
            println("Network error: ${e.message}")
        else ->
            println("Failed to get history: $e")
    }
}

Best Practices

1. Paginate Results

For apps with many transactions, use the limit parameter:
suspend fun loadPage(pageSize: UInt = 20u): List<Transaction> {
    return withContext(Dispatchers.IO) {
        sdk.getTransactionHistory(txType = null, tokenAddress = null, limit = pageSize)
    }
}

2. Refresh After Operations

Fetch updated history after deposits, withdrawals, or transfers:
val shieldResult = withContext(Dispatchers.IO) {
    sdk.shield(tokenAddress = tokenAddress, amount = amount)
}

// Refresh transaction list
val updatedHistory = withContext(Dispatchers.IO) {
    sdk.getTransactionHistory(txType = null, tokenAddress = null, limit = 20u)
}

Next Steps