89 lines
3.0 KiB
Kotlin
89 lines
3.0 KiB
Kotlin
package cash.z.android.wallet.data
|
|
|
|
import androidx.room.Room
|
|
import androidx.room.RoomDatabase
|
|
import cash.z.android.wallet.ZcashWalletApplication
|
|
import cash.z.android.wallet.vo.WalletTransaction
|
|
import cash.z.android.wallet.vo.WalletTransactionStatus
|
|
import cash.z.wallet.sdk.dao.BlockDao
|
|
import cash.z.wallet.sdk.dao.NoteDao
|
|
import cash.z.wallet.sdk.dao.TransactionDao
|
|
import cash.z.wallet.sdk.db.DerivedDataDb
|
|
import cash.z.wallet.sdk.vo.NoteQuery
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.channels.BroadcastChannel
|
|
import kotlinx.coroutines.channels.ReceiveChannel
|
|
import kotlinx.coroutines.channels.produce
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.isActive
|
|
import java.math.BigDecimal
|
|
|
|
class ReceivedTransactionRepository(val scope: CoroutineScope) : TransactionRepository {
|
|
|
|
private var db = injectDb()
|
|
private lateinit var transactions: TransactionDao
|
|
private lateinit var blocks: BlockDao
|
|
private lateinit var notes: NoteDao
|
|
|
|
private var existingTransactions = linkedSetOf<WalletTransaction>()
|
|
private var existingBalance = BigDecimal.ZERO
|
|
private var balanceChannel = BroadcastChannel<BigDecimal>(100)
|
|
|
|
private fun injectDb() = Room
|
|
.databaseBuilder(ZcashWalletApplication.instance, DerivedDataDb::class.java, "tmp")
|
|
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
|
.fallbackToDestructiveMigration()
|
|
.build()
|
|
.apply {
|
|
transactions = transactionDao()
|
|
blocks = blockDao()
|
|
notes = noteDao()
|
|
}
|
|
|
|
|
|
/**
|
|
* Just send a sample stream of balances, every so often
|
|
*/
|
|
override fun balance() = balanceChannel.openSubscription()
|
|
|
|
/**
|
|
* Just send a sample stream of transactions, every so often
|
|
*/
|
|
override fun transactions(): ReceiveChannel<WalletTransaction> = scope.produce {
|
|
while (isActive) {
|
|
delay(1500L)
|
|
val newTransactions = checkForNewTransactions()
|
|
newTransactions?.forEach {
|
|
existingTransactions.add(it)
|
|
send(it)
|
|
updateBalance(it)
|
|
}
|
|
}
|
|
}
|
|
|
|
private suspend fun updateBalance(tx: WalletTransaction) {
|
|
val multiplier = when (tx.status) {
|
|
WalletTransactionStatus.SENT -> -1.0
|
|
WalletTransactionStatus.RECEIVED -> 1.0
|
|
}
|
|
existingBalance += tx.amount.multiply(BigDecimal(multiplier))
|
|
balanceChannel.send(existingBalance)
|
|
}
|
|
|
|
private fun checkForNewTransactions(): Set<WalletTransaction>? {
|
|
val count = notes.count()
|
|
if(count == existingTransactions.size) return null
|
|
|
|
val notes = notes.getAll().map { toWalletTransaction(it) }
|
|
return notes.subtract(existingTransactions)
|
|
}
|
|
|
|
private fun toWalletTransaction(note: NoteQuery): WalletTransaction {
|
|
return WalletTransaction(
|
|
height = note.height,
|
|
status = WalletTransactionStatus.RECEIVED,
|
|
amount = BigDecimal(note.value / 1e8),
|
|
timestamp = note.time
|
|
)
|
|
}
|
|
} |