checkpoint: things are back functional after some heavy re-writing
This commit is contained in:
parent
2e6531c860
commit
25945a5ef9
|
@ -6,15 +6,16 @@ import cash.z.android.wallet.BuildConfig
|
|||
import cash.z.android.wallet.ChipBucket
|
||||
import cash.z.android.wallet.InMemoryChipBucket
|
||||
import cash.z.android.wallet.ZcashWalletApplication
|
||||
import cash.z.android.wallet.data.StaticTransactionRepository
|
||||
import cash.z.android.wallet.data.*
|
||||
import cash.z.android.wallet.extention.toDbPath
|
||||
import cash.z.android.wallet.sample.*
|
||||
import cash.z.android.wallet.sample.CarolWallet
|
||||
import cash.z.android.wallet.sample.SampleProperties.COMPACT_BLOCK_PORT
|
||||
import cash.z.android.wallet.sample.SampleProperties.DEFAULT_BLOCK_POLL_FREQUENCY_MILLIS
|
||||
import cash.z.android.wallet.sample.SampleProperties.DEFAULT_SERVER
|
||||
import cash.z.android.wallet.sample.SampleProperties.DEFAULT_TRANSACTION_POLL_FREQUENCY_MILLIS
|
||||
import cash.z.android.wallet.sample.SampleProperties.PREFS_SERVER_NAME
|
||||
import cash.z.android.wallet.sample.SampleProperties.PREFS_WALLET_DISPLAY_NAME
|
||||
import cash.z.android.wallet.sample.Servers
|
||||
import cash.z.android.wallet.sample.WalletConfig
|
||||
import cash.z.android.wallet.ui.util.Broom
|
||||
import cash.z.wallet.sdk.block.*
|
||||
import cash.z.wallet.sdk.data.*
|
||||
|
@ -28,6 +29,7 @@ import cash.z.wallet.sdk.service.LightWalletGrpcService
|
|||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
@ -168,30 +170,30 @@ internal object SynchronizerModule {
|
|||
fun provideManager(wallet: Wallet, repository: TransactionRepository, service: LightWalletService): ActiveTransactionManager {
|
||||
return ActiveTransactionManager(repository, service, wallet)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSynchronizer(
|
||||
processor: CompactBlockProcessor,
|
||||
repository: TransactionRepository,
|
||||
manager: ActiveTransactionManager,
|
||||
wallet: Wallet
|
||||
): Synchronizer {
|
||||
return SdkSynchronizer(processor, repository, manager, wallet, DEFAULT_STALE_TOLERANCE)
|
||||
}
|
||||
//
|
||||
// @JvmStatic
|
||||
// @Provides
|
||||
// @Singleton
|
||||
// fun provideSynchronizer(
|
||||
// processor: CompactBlockProcessor,
|
||||
// repository: TransactionRepository,
|
||||
// manager: ActiveTransactionManager,
|
||||
// wallet: Wallet
|
||||
// ): Synchronizer {
|
||||
// return SdkSynchronizer(processor, repository, manager, wallet, DEFAULT_STALE_TOLERANCE)
|
||||
// }
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBroom(
|
||||
service: LightWalletService,
|
||||
sender: TransactionSender,
|
||||
wallet: Wallet,
|
||||
rustBackend: RustBackendWelding,
|
||||
walletConfig: WalletConfig
|
||||
): Broom {
|
||||
return Broom(
|
||||
service,
|
||||
sender,
|
||||
rustBackend,
|
||||
walletConfig.cacheDbName,
|
||||
wallet
|
||||
|
@ -204,4 +206,33 @@ internal object SynchronizerModule {
|
|||
fun provideChipBucket(): ChipBucket {
|
||||
return InMemoryChipBucket()
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTransactionManager(): TransactionManager {
|
||||
return PersistentTransactionManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTransactionSender(manager: TransactionManager, service: LightWalletService): TransactionSender {
|
||||
return PersistentTransactionMonitor(manager, service)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTransactionEncoder(wallet: Wallet, repository: TransactionRepository): RawTransactionEncoder {
|
||||
return WalletTransactionEncoder(wallet, repository)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDataSynchronizer(wallet: Wallet, encoder: RawTransactionEncoder, sender: TransactionSender) : DataSyncronizer {
|
||||
return StableSynchronizer(wallet, encoder, sender)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
|
||||
class PersistentTransactionManager: TransactionManager {
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
override suspend fun manageCreation(encoder: RawTransactionEncoder, value: Long, toAddress: String, memo: String) {
|
||||
twig("managing the creation of a transaction")
|
||||
encoder.create(value, toAddress, memo)
|
||||
|
||||
}
|
||||
|
||||
override suspend fun manageSubmission(service: LightWalletService, rawTransaction: ByteArray) {
|
||||
try {
|
||||
// TODO: stuff before you send
|
||||
twig("managing the preparation to submit transaction")
|
||||
val response = service.submitTransaction(rawTransaction)
|
||||
twig("management of submit transaction completed with response: ${response.errorCode}: ${response.errorMessage}")
|
||||
// TODO: stuff after sending
|
||||
if (response.errorCode < 0) {
|
||||
} else {
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
twig("error while managing submitting transaction: ${t.message}")
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAllPending(): List<ByteArray> {
|
||||
return listOf()
|
||||
}
|
||||
}
|
|
@ -1,51 +1,31 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import kotlinx.coroutines.channels.actor
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PersistentTransactionSender(
|
||||
private val manager: TransactionManager,
|
||||
private val factory: RawTransactionFactory
|
||||
) : TransactionSender {
|
||||
|
||||
/**
|
||||
* Generates newly persisted information about a transaction so that other processes can send.
|
||||
*/
|
||||
override fun sendToAddress(zatoshi: Long, toAddress: String, memo: String, fromAccountId: Int) {
|
||||
val txId = manager.new() // creates a new transaction with a lifecycle of CREATING
|
||||
try {
|
||||
val rawTransaction = factory.create(zatoshi, toAddress, memo)
|
||||
manager.setRawTransaction(txId, rawTransaction) // returns new transaction with lifecycle of CREATED
|
||||
} catch (t: Throwable) {
|
||||
manager.setCreationError(txId, t.message.toTxError())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PersistentTransactionMonitor (
|
||||
private val scope: CoroutineScope,
|
||||
private val manager: TransactionManager,
|
||||
private val service: LightWalletService
|
||||
) {
|
||||
private val channel: SendChannel<TransactionUpdateRequest>
|
||||
) : TransactionSender {
|
||||
private lateinit var channel: SendChannel<TransactionUpdateRequest>
|
||||
private var monitoringJob: Job? = null
|
||||
private val initialMonitorDelay = 45_000L
|
||||
|
||||
init {
|
||||
channel = scope.startActor()
|
||||
}
|
||||
|
||||
fun update() = scope.launch {
|
||||
channel.send(SubmitPending)
|
||||
fun CoroutineScope.requestUpdate() = launch {
|
||||
if (!channel.isClosedForSend) {
|
||||
channel.send(SubmitPending)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an actor that listens for signals about what to do with transactions. This actor's lifespan is within the
|
||||
* provided [scope] and it will live until the scope is cancelled.
|
||||
*/
|
||||
fun CoroutineScope.startActor() = actor<TransactionUpdateRequest> {
|
||||
private fun CoroutineScope.startActor() = actor<TransactionUpdateRequest> {
|
||||
var pendingTransactionDao = 0 // actor state:
|
||||
for (msg in channel) { // iterate over incoming messages
|
||||
when (msg) {
|
||||
|
@ -54,27 +34,59 @@ class PersistentTransactionMonitor (
|
|||
}
|
||||
}
|
||||
|
||||
private fun submitPendingTransactions() {
|
||||
val transactions = manager.getAllPendingRawTransactions().forEach { (txId, rawTransaction) ->
|
||||
submitPendingTransaction(txId, rawTransaction)
|
||||
private fun CoroutineScope.startMonitor() = launch {
|
||||
while (!channel.isClosedForSend && isActive) {
|
||||
delay(calculateDelay())
|
||||
requestUpdate()
|
||||
}
|
||||
twig("TransactionMonitor stopping!")
|
||||
}
|
||||
|
||||
private fun submitPendingTransaction(txId: Long, rawTransaction: ByteArray) {
|
||||
try {
|
||||
manager.setSubmissionStarted(txId)
|
||||
val response = service.submitTransaction(rawTransaction)
|
||||
if (response.errorCode < 0) {
|
||||
manager.setSubmissionComplete(txId, false, response.errorMessage.toTxError())
|
||||
} else {
|
||||
manager.setSubmissionComplete(txId, true)
|
||||
private fun calculateDelay(): Long {
|
||||
return initialMonitorDelay
|
||||
}
|
||||
|
||||
override fun start(scope: CoroutineScope) {
|
||||
twig("TransactionMonitor starting!")
|
||||
channel = scope.startActor()
|
||||
monitoringJob?.cancel()
|
||||
monitoringJob = scope.startMonitor()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
channel.close()
|
||||
monitoringJob?.cancel()?.also { monitoringJob = null }
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates newly persisted information about a transaction so that other processes can send.
|
||||
*/
|
||||
override suspend fun sendToAddress(
|
||||
encoder: RawTransactionEncoder,
|
||||
zatoshi: Long,
|
||||
toAddress: String,
|
||||
memo: String,
|
||||
fromAccountId: Int
|
||||
) = withContext(IO) {
|
||||
manager.manageCreation(encoder, zatoshi, toAddress, memo)
|
||||
requestUpdate()
|
||||
Unit
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit all pending transactions that have not expired.
|
||||
*/
|
||||
private suspend fun submitPendingTransactions() = withContext(IO) {
|
||||
twig("received request to submit pending transactions")
|
||||
with(manager) {
|
||||
getAllPending().also { twig("found ${it.size} pending txs to submit") }.forEach { rawTx ->
|
||||
manageSubmission(service, rawTx)
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
manager.setSubmissionComplete(txId, false, t.message.toTxError())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sealed class TransactionUpdateRequest
|
||||
object SubmitPending : TransactionUpdateRequest()
|
||||
|
||||
|
@ -97,4 +109,38 @@ SUBMITTED
|
|||
INVALID
|
||||
** attempting submission
|
||||
** attempted submission
|
||||
|
||||
bookkeeper, register, treasurer, mint, ledger
|
||||
|
||||
|
||||
private fun checkTx(transactionId: Long) {
|
||||
if (transactionId < 0) {
|
||||
throw SweepException.Creation
|
||||
} else {
|
||||
twig("successfully created transaction!")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRawTx(transactionRaw: ByteArray?) {
|
||||
if (transactionRaw == null) {
|
||||
throw SweepException.Disappeared
|
||||
} else {
|
||||
twig("found raw transaction in the dataDb")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkResponse(response: Service.SendResponse) {
|
||||
if (response.errorCode < 0) {
|
||||
throw SweepException.IncompletePass(response)
|
||||
} else {
|
||||
twig("successfully submitted. error code: ${response.errorCode}")
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SweepException(val errorMessage: String) : RuntimeException(errorMessage) {
|
||||
object Creation : SweepException("failed to create raw transaction")
|
||||
object Disappeared : SweepException("unable to find a matching raw transaction. This means the rust backend said it created a TX but when we looked for it in the DB it was missing!")
|
||||
class IncompletePass(response: Service.SendResponse) : SweepException("submit failed with error code: ${response.errorCode} and message ${response.errorMessage}")
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,8 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
interface RawTransactionEncoder {
|
||||
/**
|
||||
* Creates a raw transaction that is unsigned.
|
||||
*/
|
||||
suspend fun create(zatoshi: Long, toAddress: String, memo: String = ""): ByteArray
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
interface RawTransactionFactory {
|
||||
/**
|
||||
* Creates a raw transaction that is unsigned.
|
||||
*/
|
||||
fun create(value: Long, toAddress: String, memo: String = ""): ByteArray
|
||||
}
|
|
@ -1,30 +1,71 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import cash.z.android.wallet.ui.util.BaseLifecycleObserver
|
||||
import cash.z.wallet.sdk.data.ActiveTransaction
|
||||
import cash.z.wallet.sdk.data.TransactionState
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* A synchronizer that attempts to remain operational, despite any number of errors that can occur.
|
||||
*
|
||||
* @param lifecycleOwner the lifecycle to observe while synchronizing
|
||||
*/
|
||||
class StableSynchronizer(
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
sender: TransactionSender
|
||||
) : BaseLifecycleObserver(), TransactionSender by sender {
|
||||
init {
|
||||
lifecycleOwner.lifecycle.addObserver(this)
|
||||
@ExperimentalCoroutinesApi
|
||||
class StableSynchronizer @Inject constructor(
|
||||
private val wallet: Wallet,
|
||||
private val encoder: RawTransactionEncoder,
|
||||
private val sender: TransactionSender
|
||||
) : DataSyncronizer {
|
||||
|
||||
private val balanceChannel = ConflatedBroadcastChannel<Wallet.WalletBalance>()
|
||||
private val progressChannel = ConflatedBroadcastChannel<Int>()
|
||||
private val pendingChannel = ConflatedBroadcastChannel<List<PendingTransaction>>()
|
||||
|
||||
override fun start(scope: CoroutineScope) {
|
||||
twig("Staring sender!")
|
||||
sender.start(scope)
|
||||
}
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
//
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
|
||||
override fun stop() {
|
||||
sender.stop()
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
|
||||
//
|
||||
// Channels
|
||||
//
|
||||
|
||||
override fun balances(): ReceiveChannel<Wallet.WalletBalance> {
|
||||
return balanceChannel.openSubscription()
|
||||
}
|
||||
|
||||
override fun progress(): ReceiveChannel<Int> {
|
||||
return progressChannel.openSubscription()
|
||||
}
|
||||
|
||||
override fun pendingTransactions(): ReceiveChannel<List<PendingTransaction>> {
|
||||
return pendingChannel.openSubscription()
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Send / Receive
|
||||
//
|
||||
|
||||
override suspend fun getAddress(accountId: Int): String = withContext(IO) { wallet.getAddress() }
|
||||
|
||||
override suspend fun sendToAddress(
|
||||
zatoshi: Long,
|
||||
toAddress: String,
|
||||
memo: String,
|
||||
fromAccountId: Int
|
||||
) = withContext(IO) {
|
||||
sender.sendToAddress(encoder, zatoshi, toAddress, memo, fromAccountId)
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,13 +75,22 @@ class StableSynchronizer(
|
|||
// override fun transactions(): Flow<WalletTransaction> {
|
||||
// }
|
||||
//
|
||||
// override fun balance(): Flow<Wallet.WalletBalance> {
|
||||
// }
|
||||
//
|
||||
// override fun progress(): Flow<Int> {
|
||||
// }
|
||||
//
|
||||
// override fun status(): Flow<FlowSynchronizer.SyncStatus> {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
interface DataSyncronizer {
|
||||
fun start(scope: CoroutineScope)
|
||||
fun stop()
|
||||
|
||||
suspend fun getAddress(accountId: Int = 0): String
|
||||
suspend fun sendToAddress(zatoshi: Long, toAddress: String, memo: String = "", fromAccountId: Int = 0)
|
||||
|
||||
fun balances(): ReceiveChannel<Wallet.WalletBalance>
|
||||
fun progress(): ReceiveChannel<Int>
|
||||
fun pendingTransactions(): ReceiveChannel<List<PendingTransaction>>
|
||||
}
|
|
@ -1,37 +1,64 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Manage transactions with the main purpose of reporting which ones are still pending, particularly after failed
|
||||
* attempts or dropped connectivity. The intent is to help see transactions through to completion.
|
||||
*/
|
||||
interface TransactionManager {
|
||||
/**
|
||||
* Initialize a transaction and return its ID.
|
||||
*
|
||||
* @return the id of the transaction to use with subsequent calls to this manager instance.
|
||||
*/
|
||||
fun new(): Long
|
||||
suspend fun manageCreation(encoder: RawTransactionEncoder, value: Long, toAddress: String, memo: String)
|
||||
suspend fun manageSubmission(service: LightWalletService, rawTransaction: ByteArray)
|
||||
suspend fun getAllPending(): List<ByteArray>
|
||||
//
|
||||
// /**
|
||||
// * Initialize a transaction and return its ID.
|
||||
// *
|
||||
// * @return the id of the transaction to use with subsequent calls to this manager instance.
|
||||
// */
|
||||
// fun new(): Long
|
||||
//
|
||||
// /**
|
||||
// * Set the rawTransaction data for the given transaction. Typically, this would transition the state of the
|
||||
// * transaction to something like CREATED. Some implementations might derive the state, based on whether this raw
|
||||
// * transaction data has been provided.
|
||||
// *
|
||||
// * @param txId the id of the transaction to update
|
||||
// * @param rawTransaction the raw transaction data
|
||||
// */
|
||||
// fun setRawTransaction(txId: Long, rawTransaction: ByteArray)
|
||||
//
|
||||
// /**
|
||||
// * Signal that there has been an error while attempting to create a transaction.
|
||||
// *
|
||||
// * @param txId the id of the transaction to update
|
||||
// * @param error information about the error that occurred
|
||||
// */
|
||||
// fun setCreationError(txId: Long, error: TransactionError)
|
||||
//
|
||||
// fun setSubmissionStarted(txId: Long)
|
||||
// fun setSubmissionComplete(txId: Long, isSuccess: Boolean, error: TransactionError? = null)
|
||||
// fun getAllPendingRawTransactions(): Map<Long, ByteArray>
|
||||
|
||||
/**
|
||||
* Set the rawTransaction data for the given transaction. Typically, this would transition the state of the
|
||||
* transaction to something like CREATED. Some implementations might derive the state, based on whether this raw
|
||||
* transaction data has been provided.
|
||||
*
|
||||
* @param txId the id of the transaction to update
|
||||
* @param rawTransaction the raw transaction data
|
||||
*/
|
||||
fun setRawTransaction(txId: Long, rawTransaction: ByteArray)
|
||||
|
||||
/**
|
||||
* Signal that there has been an error while attempting to create a transaction.
|
||||
*
|
||||
* @param txId the id of the transaction to update
|
||||
* @param error information about the error that occurred
|
||||
*/
|
||||
fun setCreationError(txId: Long, error: TransactionError)
|
||||
|
||||
fun setSubmissionStarted(txId: Long)
|
||||
fun setSubmissionComplete(txId: Long, isSuccess: Boolean, error: TransactionError? = null)
|
||||
fun getAllPendingRawTransactions(): Map<Long, ByteArray>
|
||||
}
|
||||
|
||||
|
||||
interface TransactionError {
|
||||
val message: String
|
||||
}
|
||||
}
|
||||
|
||||
data class PendingTransaction(
|
||||
val id: Long = -1,
|
||||
val isMined: Boolean = false,
|
||||
val hasRaw: Boolean = false,
|
||||
val submitCount: Int = 0,
|
||||
val expiryHeight: Int = -1,
|
||||
val expiryTime: Long = -1,
|
||||
val errorMessage: String? = null
|
||||
)
|
||||
|
||||
fun PendingTransaction.isFailure(): Boolean {
|
||||
return errorMessage != null
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
interface TransactionSender {
|
||||
fun sendToAddress(zatoshi: Long, toAddress: String, memo: String, fromAccountId: Int)
|
||||
fun start(scope: CoroutineScope)
|
||||
fun stop()
|
||||
suspend fun sendToAddress(encoder: RawTransactionEncoder, zatoshi: Long, toAddress: String, memo: String = "", fromAccountId: Int = 0)
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package cash.z.android.wallet.data
|
||||
|
||||
import cash.z.wallet.sdk.data.TransactionRepository
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class WalletTransactionEncoder(
|
||||
private val wallet: Wallet,
|
||||
private val repository: TransactionRepository
|
||||
) : RawTransactionEncoder {
|
||||
override suspend fun create(zatoshi: Long, toAddress: String, memo: String): ByteArray = withContext(IO) {
|
||||
val transactionId = wallet.createRawSendTransaction(zatoshi, toAddress, memo)
|
||||
repository.findTransactionById(transactionId)?.raw!!
|
||||
}
|
||||
}
|
|
@ -17,12 +17,13 @@ import androidx.navigation.Navigation
|
|||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import cash.z.android.wallet.*
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.data.StableSynchronizer
|
||||
import cash.z.android.wallet.databinding.ActivityMainBinding
|
||||
import cash.z.android.wallet.di.annotation.ActivityScope
|
||||
import cash.z.android.wallet.extention.Toaster
|
||||
import cash.z.android.wallet.extention.alert
|
||||
import cash.z.android.wallet.extention.copyToClipboard
|
||||
import cash.z.android.wallet.sample.WalletConfig
|
||||
import cash.z.android.wallet.ui.fragment.ScanFragment
|
||||
import cash.z.android.wallet.ui.presenter.BalancePresenter
|
||||
import cash.z.android.wallet.ui.presenter.MainPresenter
|
||||
|
@ -34,10 +35,11 @@ import cash.z.android.wallet.ui.util.Analytics.Tap.*
|
|||
import cash.z.android.wallet.ui.util.Analytics.trackAction
|
||||
import cash.z.android.wallet.ui.util.Analytics.trackFunnelStep
|
||||
import cash.z.android.wallet.ui.util.Broom
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
@ -46,14 +48,11 @@ import kotlin.random.Random
|
|||
class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.BarcodeCallback, MainPresenter.MainView {
|
||||
|
||||
@Inject
|
||||
lateinit var synchronizer: Synchronizer
|
||||
lateinit var synchronizer: DataSyncronizer
|
||||
|
||||
@Inject
|
||||
lateinit var mainPresenter: MainPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var walletConfig: WalletConfig
|
||||
|
||||
@Inject
|
||||
lateinit var broom: Broom
|
||||
|
||||
|
@ -72,14 +71,13 @@ class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.Bar
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
this.lifecycle
|
||||
|
||||
chipBucket.restore()
|
||||
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
|
||||
binding.activity = this
|
||||
initAppBar()
|
||||
loadMessages = generateFunLoadMessages().shuffled()
|
||||
synchronizer.start(this)
|
||||
synchronizer.onSynchronizerErrorListener = ::onSynchronizerError
|
||||
|
||||
balancePresenter = BalancePresenter()
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,8 @@ class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.Bar
|
|||
super.onResume()
|
||||
chipBucket.restore()
|
||||
launch {
|
||||
balancePresenter.start(this, synchronizer)
|
||||
synchronizer.start(this)
|
||||
balancePresenter.start(this, synchronizer.balances())
|
||||
mainPresenter.start()
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +105,6 @@ class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.Bar
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
synchronizer.stop()
|
||||
Analytics.clear()
|
||||
}
|
||||
|
||||
|
@ -421,7 +419,7 @@ class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.Bar
|
|||
}
|
||||
|
||||
override fun orderUpdated(processing: MainPresenter.PurchaseResult.Processing) {
|
||||
Toaster.short(processing.state.toString())
|
||||
Toaster.short(processing.pendingTransaction.toString())
|
||||
}
|
||||
|
||||
fun onSynchronizerError(error: Throwable?): Boolean {
|
||||
|
@ -454,7 +452,9 @@ class MainActivity : BaseActivity(), Animator.AnimatorListener, ScanFragment.Bar
|
|||
fun copyAddress(view: View) {
|
||||
trackAction(TAPPED_COPY_ADDRESS)
|
||||
Toaster.short("Address copied!")
|
||||
copyToClipboard(synchronizer.getAddress())
|
||||
launch {
|
||||
copyToClipboard(synchronizer.getAddress())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import androidx.annotation.IdRes
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.ui.presenter.ProgressPresenter
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -15,7 +16,7 @@ abstract class ProgressFragment(
|
|||
ProgressPresenter.ProgressView {
|
||||
|
||||
@Inject
|
||||
protected lateinit var synchronizer: Synchronizer
|
||||
protected lateinit var synchronizer: DataSyncronizer
|
||||
|
||||
protected lateinit var progressPresenter: ProgressPresenter
|
||||
private lateinit var progressBar: ProgressBar
|
||||
|
|
|
@ -10,12 +10,14 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import cash.z.android.qrecycler.QRecycler
|
||||
import cash.z.android.wallet.R
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||
import cash.z.android.wallet.ui.util.AddressPartNumberSpan
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import kotlinx.android.synthetic.main.fragment_receive.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -27,7 +29,7 @@ class ReceiveFragment : BaseFragment() {
|
|||
lateinit var qrecycler: QRecycler
|
||||
|
||||
@Inject
|
||||
lateinit var synchronizer: Synchronizer
|
||||
lateinit var synchronizer: DataSyncronizer
|
||||
|
||||
lateinit var addressParts: Array<TextView>
|
||||
|
||||
|
@ -61,7 +63,9 @@ class ReceiveFragment : BaseFragment() {
|
|||
super.onResume()
|
||||
|
||||
// TODO: replace these with channels. For now just wire the logic together
|
||||
onAddressLoaded(loadAddress())
|
||||
launch {
|
||||
onAddressLoaded(synchronizer.getAddress())
|
||||
}
|
||||
// converter.scanBlocks()
|
||||
}
|
||||
|
||||
|
@ -85,12 +89,6 @@ class ReceiveFragment : BaseFragment() {
|
|||
|
||||
addressParts[index].text = textSpan
|
||||
}
|
||||
|
||||
// TODO: replace with tiered load. First check memory reference (textview contents?) then check DB, then load from JNI and write to DB
|
||||
private fun loadAddress(): String {
|
||||
return synchronizer.getAddress()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Module
|
||||
|
|
|
@ -66,7 +66,7 @@ class SyncFragment : ProgressFragment(R.id.progress_sync) {
|
|||
(view?.parent as? ViewGroup)?.doOnPreDraw {
|
||||
startPostponedEnterTransition()
|
||||
}
|
||||
synchronizer.onSynchronizerErrorListener = ::onSynchronizerError
|
||||
// synchronizer.onSynchronizerErrorListener = ::onSynchronizerError
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
|
@ -19,6 +19,7 @@ import cash.z.android.wallet.ui.presenter.BalancePresenter
|
|||
import cash.z.android.wallet.ui.presenter.TransactionPresenter
|
||||
import cash.z.android.wallet.ui.presenter.TransactionPresenterModule
|
||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.ext.MINERS_FEE_ZATOSHI
|
||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
|
@ -114,10 +115,6 @@ class Zcon1HomeFragment : BaseFragment(), BalancePresenter.BalanceView, Transact
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
chipBucket.setOnBucketChangedListener(this)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mainActivity?.balancePresenter?.addBalanceView(this)
|
||||
chipBucket.setOnBucketChangedListener(this)
|
||||
launch {
|
||||
|
@ -125,8 +122,8 @@ class Zcon1HomeFragment : BaseFragment(), BalancePresenter.BalanceView, Transact
|
|||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mainActivity?.balancePresenter?.removeBalanceView(this)
|
||||
chipBucket.removeOnBucketChangedListener(this)
|
||||
transactionPresenter.stop()
|
||||
|
|
|
@ -29,12 +29,12 @@ class BalancePresenter {
|
|||
// LifeCycle
|
||||
//
|
||||
|
||||
fun start(scope: CoroutineScope, synchronizer: Synchronizer) {
|
||||
fun start(scope: CoroutineScope, balanceChannel: ReceiveChannel<Wallet.WalletBalance>) {
|
||||
Twig.sprout("BalancePresenter")
|
||||
twig("balancePresenter starting!")
|
||||
balanceJob?.cancel()
|
||||
balanceJob = Job()
|
||||
balanceJob = scope.launchBalanceBinder(synchronizer.balances())
|
||||
balanceJob = scope.launchBalanceBinder(balanceChannel)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||
import cash.z.android.wallet.ui.fragment.HistoryFragment
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
|
@ -19,7 +20,7 @@ import kotlin.coroutines.CoroutineContext
|
|||
|
||||
class HistoryPresenter @Inject constructor(
|
||||
private val view: HistoryFragment,
|
||||
private var synchronizer: Synchronizer
|
||||
private var synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
private var job: Job? = null
|
||||
|
@ -32,7 +33,7 @@ class HistoryPresenter @Inject constructor(
|
|||
job?.cancel()
|
||||
job = Job()
|
||||
twig("historyPresenter starting!")
|
||||
view.launchTransactionBinder(synchronizer.allTransactions())
|
||||
// view.launchTransactionBinder(synchronizer.allTransactions())
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||
import cash.z.android.wallet.extention.alert
|
||||
import cash.z.android.wallet.ui.fragment.HomeFragment
|
||||
|
@ -18,7 +19,7 @@ import javax.inject.Singleton
|
|||
|
||||
class HomePresenter @Inject constructor(
|
||||
private val view: HomeFragment,
|
||||
private val synchronizer: Synchronizer
|
||||
private val synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
private var job: Job? = null
|
||||
|
@ -32,15 +33,15 @@ class HomePresenter @Inject constructor(
|
|||
}
|
||||
|
||||
override suspend fun start() {
|
||||
job?.cancel()
|
||||
job = Job()
|
||||
twig("homePresenter starting! from ${this.hashCode()}")
|
||||
with(view) {
|
||||
launchBalanceBinder(synchronizer.balances())
|
||||
launchTransactionBinder(synchronizer.allTransactions())
|
||||
launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
||||
}
|
||||
synchronizer.onSynchronizerErrorListener = view::onSynchronizerError
|
||||
// job?.cancel()
|
||||
// job = Job()
|
||||
// twig("homePresenter starting! from ${this.hashCode()}")
|
||||
// with(view) {
|
||||
// launchBalanceBinder(synchronizer.balances())
|
||||
// launchTransactionBinder(synchronizer.allTransactions())
|
||||
// launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
||||
// }
|
||||
// synchronizer.onSynchronizerErrorListener = view::onSynchronizerError
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
@ -99,11 +100,11 @@ class HomePresenter @Inject constructor(
|
|||
}
|
||||
|
||||
fun onCancelActiveTransaction(transaction: ActiveSendTransaction) {
|
||||
twig("requesting to cancel send for transaction ${transaction.internalId}")
|
||||
val isTooLate = !synchronizer.cancelSend(transaction)
|
||||
if (isTooLate) {
|
||||
view.onCancelledTooLate()
|
||||
}
|
||||
// twig("requesting to cancel send for transaction ${transaction.internalId}")
|
||||
// val isTooLate = !synchronizer.cancelSend(transaction)
|
||||
// if (isTooLate) {
|
||||
// view.onCancelledTooLate()
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.data.PendingTransaction
|
||||
import cash.z.android.wallet.data.isFailure
|
||||
import cash.z.android.wallet.ui.activity.MainActivity
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.wallet.sdk.data.*
|
||||
|
@ -13,7 +16,7 @@ import javax.inject.Inject
|
|||
|
||||
class MainPresenter @Inject constructor(
|
||||
private val view: MainActivity,
|
||||
private val synchronizer: Synchronizer
|
||||
private val synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
interface MainView : PresenterView {
|
||||
|
@ -34,7 +37,7 @@ class MainPresenter @Inject constructor(
|
|||
|
||||
purchaseJob?.cancel()
|
||||
purchaseJob = Job()
|
||||
purchaseJob = view.launchPurchaseBinder(synchronizer.activeTransactions())
|
||||
purchaseJob = view.launchPurchaseBinder(synchronizer.pendingTransactions())
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
@ -43,7 +46,7 @@ class MainPresenter @Inject constructor(
|
|||
purchaseJob?.cancel()?.also { purchaseJob = null }
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchPurchaseBinder(channel: ReceiveChannel<Map<ActiveTransaction, TransactionState>>) = launch {
|
||||
private fun CoroutineScope.launchPurchaseBinder(channel: ReceiveChannel<List<PendingTransaction>>) = launch {
|
||||
twig("main purchase binder starting!")
|
||||
for (new in channel) {
|
||||
twig("main polled a purchase info")
|
||||
|
@ -57,18 +60,18 @@ class MainPresenter @Inject constructor(
|
|||
// Events
|
||||
//
|
||||
|
||||
private fun bind(activeTransactions: Map<ActiveTransaction, TransactionState>) {
|
||||
val newestState = activeTransactions.entries.last().value
|
||||
if (newestState is TransactionState.Failure) {
|
||||
view.orderFailed(PurchaseResult.Failure(newestState.reason))
|
||||
private fun bind(activeTransactions: List<PendingTransaction>) {
|
||||
val newest = activeTransactions.last()
|
||||
if (newest.isFailure()) {
|
||||
view.orderFailed(PurchaseResult.Failure(newest.errorMessage))
|
||||
} else {
|
||||
view.orderUpdated(PurchaseResult.Processing(newestState))
|
||||
view.orderUpdated(PurchaseResult.Processing(newest))
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PurchaseResult {
|
||||
data class Processing(val state: TransactionState = TransactionState.Creating) : PurchaseResult()
|
||||
data class Failure(val reason: String = "") : PurchaseResult()
|
||||
data class Processing(val pendingTransaction: PendingTransaction) : PurchaseResult()
|
||||
data class Failure(val reason: String? = "") : PurchaseResult()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.data.Twig
|
||||
|
@ -11,7 +12,7 @@ import kotlin.coroutines.CoroutineContext
|
|||
|
||||
class ProgressPresenter @Inject constructor(
|
||||
private val view: ProgressView,
|
||||
private var synchronizer: Synchronizer
|
||||
private var synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
private var job: Job? = null
|
||||
|
@ -29,7 +30,6 @@ class ProgressPresenter @Inject constructor(
|
|||
job?.cancel()
|
||||
job = Job()
|
||||
Twig.sprout("ProgressPresenter")
|
||||
twig("starting")
|
||||
view.launchProgressMonitor(synchronizer.progress())
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class ProgressPresenter @Inject constructor(
|
|||
}
|
||||
|
||||
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||
twig("progress monitor starting on thread ${Thread.currentThread().name}!")
|
||||
twig("Progress monitor starting")
|
||||
for (i in channel) {
|
||||
bind(i)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.R
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||
import cash.z.android.wallet.extention.toAppString
|
||||
import cash.z.android.wallet.sample.SampleProperties
|
||||
|
@ -23,7 +24,7 @@ import javax.inject.Inject
|
|||
|
||||
class SendPresenter @Inject constructor(
|
||||
private val view: SendFragment,
|
||||
private val synchronizer: Synchronizer
|
||||
private val synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
interface SendView : PresenterView {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cash.z.android.wallet.ui.presenter
|
||||
|
||||
import cash.z.android.wallet.data.DataSyncronizer
|
||||
import cash.z.android.wallet.ui.fragment.Zcon1HomeFragment
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||
|
@ -14,7 +15,7 @@ import javax.inject.Inject
|
|||
|
||||
class TransactionPresenter @Inject constructor(
|
||||
private val view: Zcon1HomeFragment,
|
||||
private val synchronizer: Synchronizer
|
||||
private val synchronizer: DataSyncronizer
|
||||
) : Presenter {
|
||||
|
||||
interface TransactionView : PresenterView {
|
||||
|
@ -35,7 +36,7 @@ class TransactionPresenter @Inject constructor(
|
|||
transactionJob?.cancel()
|
||||
transactionJob = Job()
|
||||
// transactionJob = view.launchPurchaseBinder(synchronizer.activeTransactions())
|
||||
transactionJob = view.launchTransactionBinder(synchronizer.allTransactions())
|
||||
// transactionJob = view.launchTransactionBinder(synchronizer.allTransactions())
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
package cash.z.android.wallet.ui.util
|
||||
|
||||
import cash.z.android.wallet.PokerChip
|
||||
import cash.z.android.wallet.ZcashWalletApplication
|
||||
import cash.z.android.wallet.data.StaticTransactionRepository
|
||||
import cash.z.android.wallet.data.TransactionSender
|
||||
import cash.z.android.wallet.data.WalletTransactionEncoder
|
||||
import cash.z.android.wallet.extention.toDbPath
|
||||
import cash.z.android.wallet.extention.tryIgnore
|
||||
import cash.z.android.wallet.sample.SampleProperties
|
||||
import cash.z.wallet.sdk.data.PollingTransactionRepository
|
||||
import cash.z.wallet.sdk.data.TransactionRepository
|
||||
import cash.z.wallet.sdk.data.Twig
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.ext.MINERS_FEE_ZATOSHI
|
||||
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
@ -22,7 +18,7 @@ import kotlin.properties.Delegates
|
|||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
class Broom(
|
||||
private val service: LightWalletService,
|
||||
private val sender: TransactionSender,
|
||||
private val rustBackend: RustBackendWelding,
|
||||
private val cacheDbName: String,
|
||||
private val appWallet: Wallet
|
||||
|
@ -39,7 +35,7 @@ class Broom(
|
|||
// cloneCachedBlocks() // optional?
|
||||
|
||||
try {
|
||||
val wallet = initWallet(walletSeedProvider)
|
||||
val encoder = initEncoder(walletSeedProvider)
|
||||
// verify & scan
|
||||
//TODO: for now, assume validation is happening elsewhere and just scan here
|
||||
Twig.sprout("broom-scan")
|
||||
|
@ -48,12 +44,7 @@ class Broom(
|
|||
Twig.clip("broom-scan")
|
||||
if (scanResult) {
|
||||
twig("successfully scanned blocks! Ready to sweep!!!")
|
||||
val memo = "swag shirt test"
|
||||
val address = "ztestsapling1yu2zy9aanf8pjf2qvm4qmn4k6q57y2d9fcs3vz0guthxx3m2aq57qm6hkx0580m9u9635xh6ttr"
|
||||
// val address = appWallet.getAddress()
|
||||
val transactionId = wallet.createRawSendTransaction(amount, address).also { checkTx(it) }
|
||||
val transactionRaw: ByteArray? = repository.findTransactionById(transactionId)?.raw.also { checkRawTx(it) }
|
||||
service.submitTransaction(transactionRaw!!).also { checkResponse(it) }
|
||||
sender.sendToAddress(encoder, amount, appWallet.getAddress())
|
||||
} else {
|
||||
twig("failed to scan!")
|
||||
}
|
||||
|
@ -67,34 +58,10 @@ class Broom(
|
|||
}
|
||||
}
|
||||
|
||||
private fun checkTx(transactionId: Long) {
|
||||
if (transactionId < 0) {
|
||||
throw SweepException.Creation
|
||||
} else {
|
||||
twig("successfully created transaction!")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRawTx(transactionRaw: ByteArray?) {
|
||||
if (transactionRaw == null) {
|
||||
throw SweepException.Disappeared
|
||||
} else {
|
||||
twig("found raw transaction in the dataDb")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkResponse(response: Service.SendResponse) {
|
||||
if (response.errorCode < 0) {
|
||||
throw SweepException.IncompletePass(response)
|
||||
} else {
|
||||
twig("successfully submitted. error code: ${response.errorCode}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initWallet(seedProvider: ReadOnlyProperty<Any?, ByteArray>): Wallet {
|
||||
private fun initEncoder(seedProvider: ReadOnlyProperty<Any?, ByteArray>): WalletTransactionEncoder {
|
||||
// TODO: maybe let this one live and make a new one?
|
||||
DATA_DB_PATH.absoluteFile.delete()
|
||||
return Wallet(
|
||||
val wallet = Wallet(
|
||||
ZcashWalletApplication.instance,
|
||||
rustBackend,
|
||||
DATA_DB_PATH.absolutePath,
|
||||
|
@ -107,6 +74,7 @@ class Broom(
|
|||
it.initialize()
|
||||
}
|
||||
}
|
||||
return WalletTransactionEncoder(wallet, repository)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -114,10 +82,4 @@ class Broom(
|
|||
private val DATA_DB_PATH: File = ZcashWalletApplication.instance.getDatabasePath(DATA_DB_NAME)
|
||||
}
|
||||
|
||||
|
||||
sealed class SweepException(val errorMessage: String) : RuntimeException(errorMessage) {
|
||||
object Creation : SweepException("failed to create raw transaction")
|
||||
object Disappeared : SweepException("unable to find a matching raw transaction. This means the rust backend said it created a TX but when we looked for it in the DB it was missing!")
|
||||
class IncompletePass(response: Service.SendResponse) : SweepException("submit failed with error code: ${response.errorCode} and message ${response.errorMessage}")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue