2019-12-23 11:16:00 -08:00
|
|
|
package cash.z.ecc.android.ui.send
|
|
|
|
|
|
|
|
import androidx.lifecycle.ViewModel
|
2020-01-09 09:58:57 -08:00
|
|
|
import androidx.lifecycle.viewModelScope
|
2019-12-23 11:16:00 -08:00
|
|
|
import cash.z.ecc.android.lockbox.LockBox
|
|
|
|
import cash.z.ecc.android.ui.setup.WalletSetupViewModel
|
2020-01-06 22:45:24 -08:00
|
|
|
import cash.z.wallet.sdk.Initializer
|
2019-12-23 11:16:00 -08:00
|
|
|
import cash.z.wallet.sdk.Synchronizer
|
|
|
|
import cash.z.wallet.sdk.entity.PendingTransaction
|
2020-01-08 00:45:45 -08:00
|
|
|
import cash.z.wallet.sdk.ext.ZcashSdk
|
2020-01-09 23:53:16 -08:00
|
|
|
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
2019-12-23 11:16:00 -08:00
|
|
|
import cash.z.wallet.sdk.ext.twig
|
|
|
|
import kotlinx.coroutines.flow.Flow
|
2020-01-08 00:45:45 -08:00
|
|
|
import kotlinx.coroutines.flow.flow
|
2019-12-23 11:16:00 -08:00
|
|
|
import kotlinx.coroutines.flow.onEach
|
2020-01-09 09:58:57 -08:00
|
|
|
import kotlinx.coroutines.launch
|
2019-12-23 11:16:00 -08:00
|
|
|
import javax.inject.Inject
|
|
|
|
|
2020-01-05 21:01:06 -08:00
|
|
|
class SendViewModel @Inject constructor() : ViewModel() {
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
lateinit var lockBox: LockBox
|
|
|
|
|
2020-01-06 22:45:24 -08:00
|
|
|
@Inject
|
|
|
|
lateinit var synchronizer: Synchronizer
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
lateinit var initializer: Initializer
|
|
|
|
|
|
|
|
fun send(): Flow<PendingTransaction> {
|
2020-01-09 09:58:57 -08:00
|
|
|
val memoToSend = if (includeFromAddress) "$memo\nsent from\n$fromAddress" else memo
|
2020-01-06 22:45:24 -08:00
|
|
|
val keys = initializer.deriveSpendingKeys(
|
2019-12-23 11:16:00 -08:00
|
|
|
lockBox.getBytes(WalletSetupViewModel.LockBoxKey.SEED)!!
|
|
|
|
)
|
|
|
|
return synchronizer.sendToAddress(
|
|
|
|
keys[0],
|
|
|
|
zatoshiAmount,
|
|
|
|
toAddress,
|
2020-01-09 09:58:57 -08:00
|
|
|
memoToSend
|
2019-12-23 11:16:00 -08:00
|
|
|
).onEach {
|
|
|
|
twig(it.toString())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 23:53:16 -08:00
|
|
|
suspend fun validateAddress(address: String): Synchronizer.AddressType =
|
|
|
|
synchronizer.validateAddress(address)
|
|
|
|
|
|
|
|
fun validate(maxZatoshi: Long?) = flow<String?> {
|
2020-01-08 00:45:45 -08:00
|
|
|
|
|
|
|
when {
|
|
|
|
synchronizer.validateAddress(toAddress).isNotValid -> {
|
|
|
|
emit("Please enter a valid address")
|
|
|
|
}
|
|
|
|
zatoshiAmount < ZcashSdk.MINERS_FEE_ZATOSHI -> {
|
2020-01-13 16:09:22 -08:00
|
|
|
emit("Please enter at least 0.0001")
|
2020-01-08 00:45:45 -08:00
|
|
|
}
|
2020-01-09 23:53:16 -08:00
|
|
|
maxZatoshi != null && zatoshiAmount > maxZatoshi -> {
|
|
|
|
emit( "Please enter no more than ${maxZatoshi.convertZatoshiToZecString(8)}")
|
2020-01-09 08:02:47 -08:00
|
|
|
}
|
2020-01-08 00:45:45 -08:00
|
|
|
else -> emit(null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 09:58:57 -08:00
|
|
|
fun afterInitFromAddress(block: () -> Unit) {
|
|
|
|
viewModelScope.launch {
|
|
|
|
fromAddress = synchronizer.getAddress()
|
|
|
|
block()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 10:58:10 -08:00
|
|
|
fun reset() {
|
|
|
|
fromAddress = ""
|
|
|
|
toAddress = ""
|
|
|
|
memo = ""
|
|
|
|
zatoshiAmount = -1L
|
|
|
|
includeFromAddress = false
|
|
|
|
}
|
|
|
|
|
2020-01-09 09:58:57 -08:00
|
|
|
var fromAddress: String = ""
|
2019-12-23 11:16:00 -08:00
|
|
|
var toAddress: String = ""
|
|
|
|
var memo: String = ""
|
|
|
|
var zatoshiAmount: Long = -1L
|
2020-01-09 09:58:57 -08:00
|
|
|
var includeFromAddress: Boolean = false
|
|
|
|
set(value) {
|
|
|
|
require(!value || (value && !fromAddress.isNullOrEmpty())) {
|
|
|
|
"Error: from address was empty while attempting to include it in the memo. Verify" +
|
|
|
|
" that initFromAddress() has previously been called on this viewmodel."
|
|
|
|
}
|
|
|
|
field = value
|
|
|
|
}
|
2020-01-10 10:58:10 -08:00
|
|
|
val isShielded get() = toAddress.startsWith("z")
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|