SyncStateManager
Manages subscription sync state for resuming after app restarts.
Purpose:
Persist last processed transaction ID per address
Enable subscription resumption (don't replay all history on restart)
Track sync progress
Storage:
Uses DataStore (shared preferences alternative)
Key format: "last_tx_id_{address}"
Value: Last processed transaction ID (Int)
Resume Flow:
App starts
Get last processed ID:
getLastProcessedTransactionId(address)Subscribe from that ID:
subscribeToUnshieldedTransactions(address, lastId)Process updates
Save progress:
saveLastProcessedTransactionId(address, newId)
Example:
// On app start
val lastId = syncStateManager.getLastProcessedTransactionId(address)
// lastId = 42 (from previous session)
// Subscribe from last ID (skip already processed txs)
indexerClient.subscribeToUnshieldedTransactions(address, fromTransactionId = lastId)
.collect { update ->
utxoManager.processUpdate(update)
if (update is Progress) {
syncStateManager.saveLastProcessedTransactionId(address, update.highestTransactionId)
}
}Functions
Clear all sync state (for all addresses).
Clear sync state for an address.
Get last processed transaction ID for an address.
Observe last processed transaction ID for an address.
Save last processed transaction ID for an address.