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 paginating transaction history in the Privacy
Boost React Native SDK.
Basic Usage
getTransactionHistory is async and returns a paginated result, not a raw
array. Iterate over result.data:
import { PrivacyBoost } from '@sunnyside-io/privacy-boost-react-native';
const result = await sdk.getTransactionHistory();
for (const tx of result.data) {
console.log(`${tx.txType}: ${tx.value} - ${tx.txHash}`);
}
Transaction Type
Each Transaction groups the on-chain event with zero or more shielded notes
it produced or consumed. Money movement lives in value/tokenId/notes —
not in the pre-0.2 amount/tokenAddress/receivers shape.
interface Transaction {
txHash: string; // Transaction hash
txType: string; // "shield" | "unshield" | "transfer"
direction: string; // "incoming" | "outgoing"
value: string; // Net value in wei
tokenId: bigint; // Registered token ID
createdAt: bigint; // Unix timestamp
counterparty?: string; // Other party's address or pubkey
counterpartyType?: string; // "wallet" | "privacy"
notes: TransactionNote[]; // Shielded notes affected
}
interface TransactionNote {
value: string; // Note value in wei
direction: string; // "incoming" | "outgoing"
isChange: boolean; // True if this is a change note
leafIndex?: bigint; // Merkle leaf index
nullifier?: string; // Spent-note nullifier
counterparty?: string;
counterpartyType?: string;
}
interface TransactionsResult {
data: Transaction[];
limit: number;
next?: string; // Cursor for next page (undefined = end)
}
To resolve a tokenId to a token address/symbol, call
sdk.getRegisteredTokens() once and cache the lookup.
Filtering History
By Transaction Type
// Only shields (deposits)
const shields = await sdk.getTransactionHistory('shield');
// Only unshields (withdrawals)
const unshields = await sdk.getTransactionHistory('unshield');
// Only transfers
const transfers = await sdk.getTransactionHistory('transfer');
With Limit
// First 10 transactions
const result = await sdk.getTransactionHistory(undefined, 10);
The previous page’s next cursor is the third argument:
const first = await sdk.getTransactionHistory(undefined, 25);
if (first.next) {
const second = await sdk.getTransactionHistory(undefined, 25, first.next);
}
Parameters
| Parameter | Type | Description |
|---|
txType | string? | Filter by type: "shield", "unshield", "transfer" |
limit | number? | Page size |
cursor | string? | Opaque continuation token from previous result.next |
Token filtering is not a parameter on this method — fetch all types and
filter client-side by tx.tokenId, or use sdk.getUnspentNotes(tokenAddress)
for balance-level queries.
Complete Example
import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import type {
PrivacyBoost,
Transaction,
} from '@sunnyside-io/privacy-boost-react-native';
function TransactionHistoryScreen({ sdk }: { sdk: PrivacyBoost }) {
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [cursor, setCursor] = useState<string | undefined>(undefined);
const [filter, setFilter] = useState<string | undefined>(undefined);
const [loading, setLoading] = useState(true);
const loadMore = useCallback(async () => {
setLoading(true);
try {
const page = await sdk.getTransactionHistory(filter, 25, cursor);
setTransactions((prev) => (cursor ? [...prev, ...page.data] : page.data));
setCursor(page.next);
} catch (error) {
console.log('Failed to load transactions:', error);
}
setLoading(false);
}, [sdk, filter, cursor]);
// Reset when filter changes
useEffect(() => {
setCursor(undefined);
setTransactions([]);
loadMore();
}, [filter]);
const formatDate = (timestamp: bigint) =>
new Date(Number(timestamp) * 1000).toLocaleDateString();
return (
<View style={{ padding: 16 }}>
<FlatList
data={transactions}
keyExtractor={(item) => item.txHash}
renderItem={({ item }) => (
<View style={{ paddingVertical: 8 }}>
<Text style={{ fontWeight: 'bold' }}>
{item.txType} · {item.direction}
</Text>
<Text>Value: {sdk.formatAmount(item.value, 18)}</Text>
<Text style={{ color: 'gray' }}>{formatDate(item.createdAt)}</Text>
</View>
)}
onEndReached={() => cursor && loadMore()}
onEndReachedThreshold={0.5}
ListFooterComponent={loading ? <ActivityIndicator /> : null}
ListEmptyComponent={!loading ? <Text>No transactions</Text> : null}
/>
</View>
);
}
Error Handling
import { SdkError } from '@sunnyside-io/privacy-boost-react-native';
try {
const result = await sdk.getTransactionHistory();
} catch (error) {
if (SdkError.NotAuthenticated.instanceOf(error)) {
console.log('Please log in first');
} else if (SdkError.NetworkError.instanceOf(error)) {
console.log('Network error');
} else {
console.log('Failed to get history:', error);
}
}
Best Practices
1. Page through results
Always pass a limit and follow the next cursor. Unbounded history fetches
get expensive fast for active accounts.
Transaction.tokenId is a numeric ID. Resolve to display symbol/decimals via
sdk.getRegisteredTokens() and cache the result — the registered-token list
changes rarely.
3. Refresh after operations
Call getTransactionHistory (with no cursor) after a successful shield /
unshield / transfer so the UI reflects the new state.
Next Steps