checkpoint: stable non-mock release
This commit is contained in:
parent
69e159ff2b
commit
e2c454907d
|
@ -14,8 +14,8 @@ android {
|
|||
applicationId "cash.z.android.wallet"
|
||||
minSdkVersion buildConfig.minSdkVersion
|
||||
targetSdkVersion buildConfig.targetSdkVersion
|
||||
versionCode 17 // todo: change this to 1_00_04 format, once we graduate beyond zero for the major version number because leading zeros indicate on octal number.
|
||||
versionName "0.4.9-alpha"
|
||||
versionCode 18 // todo: change this to 1_00_04 format, once we graduate beyond zero for the major version number because leading zeros indicate on octal number.
|
||||
versionName "0.5.0-alpha"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled true
|
||||
|
|
Binary file not shown.
|
@ -41,8 +41,8 @@ internal object SynchronizerModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRepository(application: ZcashWalletApplication, converter: JniConverter, twigger: Twig): TransactionRepository {
|
||||
return PollingTransactionRepository(application, SampleProperties.wallet.dataDbName, 10_000L, converter, twigger)
|
||||
fun provideRepository(application: ZcashWalletApplication, converter: JniConverter): TransactionRepository {
|
||||
return PollingTransactionRepository(application, SampleProperties.wallet.dataDbName, 10_000L)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
@ -52,7 +52,7 @@ internal object SynchronizerModule {
|
|||
return Wallet(
|
||||
context = application,
|
||||
converter = converter,
|
||||
dbDataPath = application.getDatabasePath(SampleProperties.wallet.dataDbName).absolutePath,
|
||||
dataDbPath = application.getDatabasePath(SampleProperties.wallet.dataDbName).absolutePath,
|
||||
paramDestinationDir = "${application.cacheDir.absolutePath}/params",
|
||||
seedProvider = SampleProperties.wallet.seedProvider,
|
||||
spendingKeyProvider = SampleProperties.wallet.spendingKeyProvider
|
||||
|
|
|
@ -13,15 +13,15 @@ internal fun Context.alert(
|
|||
@StringRes messageResId: Int,
|
||||
@StringRes positiveButtonResId: Int = android.R.string.ok,
|
||||
@StringRes negativeButtonResId: Int = android.R.string.cancel,
|
||||
positiveAction: () -> Unit = NO_ACTION,
|
||||
negativeAction: () -> Unit = NO_ACTION
|
||||
negativeAction: () -> Unit = NO_ACTION,
|
||||
positiveAction: () -> Unit = NO_ACTION
|
||||
) {
|
||||
alert(
|
||||
message = getString(messageResId),
|
||||
positiveButtonResId = positiveButtonResId,
|
||||
negativeButtonResId = negativeButtonResId,
|
||||
positiveAction = positiveAction,
|
||||
negativeAction = negativeAction
|
||||
negativeAction = negativeAction,
|
||||
positiveAction = positiveAction
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ internal fun Context.alert(
|
|||
message: String,
|
||||
@StringRes positiveButtonResId: Int = android.R.string.ok,
|
||||
@StringRes negativeButtonResId: Int = android.R.string.cancel,
|
||||
positiveAction: (() -> Unit) = NO_ACTION,
|
||||
negativeAction: (() -> Unit) = NO_ACTION
|
||||
negativeAction: (() -> Unit) = NO_ACTION,
|
||||
positiveAction: (() -> Unit) = NO_ACTION
|
||||
) {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setMessage(message)
|
||||
|
|
|
@ -8,8 +8,8 @@ object AliceWallet {
|
|||
const val name = "test.reference.alice"
|
||||
val seedProvider = SampleSeedProvider(name)
|
||||
val spendingKeyProvider = SampleSpendingKeySharedPref(name)
|
||||
const val cacheDbName = "testalice_cache_emulator4.db"
|
||||
const val dataDbName = "testalice_data_emulator3.db"
|
||||
const val cacheDbName = "testalice_cache_emulator7.db"
|
||||
const val dataDbName = "testalice_data_emulator7.db"
|
||||
const val defaultSendAddress = "ztestsapling1wcp9fu5d3q945nwwyqxtf0dtn6pv22hmjxa39z0034ap734mvxkqz8kug4r2u2df2keekcne322" // bob's address
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,31 @@ object BobWallet {
|
|||
val seedProvider =
|
||||
SampleSeedProvider(name)
|
||||
val spendingKeyProvider = SampleSpendingKeySharedPref(name)
|
||||
const val cacheDbName = "testbob_cache_pixel.db"
|
||||
const val dataDbName = "testbob_data_pixel.db"
|
||||
const val cacheDbName = "testbob_cache_pixel1.db"
|
||||
const val dataDbName = "testbob_data_pixel1.db"
|
||||
const val defaultSendAddress = "ztestsapling1yv696xtjn3jykdej2pqx0999eydvvyfphnw97ddk2h5luyedpqzud3r87aq0d7qna3jzjqqdcvw" // alice's address
|
||||
}
|
||||
|
||||
object CarolWallet {
|
||||
const val name = "test.reference.carol"
|
||||
val seedProvider =
|
||||
SampleSeedProvider(name)
|
||||
val spendingKeyProvider = SampleSpendingKeySharedPref(name)
|
||||
const val cacheDbName = "testcarol_cache1.db"
|
||||
const val dataDbName = "testcarol_data1.db"
|
||||
const val defaultSendAddress = "ztestsapling1jq4dz0uurs494g0n8nywuurhyy68d6g9na8th7muuvznlux3kmsyehl89xjtu0gx58u26f4xv3d" // dave's address
|
||||
}
|
||||
|
||||
object DaveWallet {
|
||||
const val name = "test.reference.dave"
|
||||
val seedProvider =
|
||||
SampleSeedProvider(name)
|
||||
val spendingKeyProvider = SampleSpendingKeySharedPref(name)
|
||||
const val cacheDbName = "testdave_cache.db"
|
||||
const val dataDbName = "testdave_data.db"
|
||||
const val defaultSendAddress = "ztestsapling1gl8rn5u3p0j9xk2vulre5fhe4rq58p4euzuxdqpgrlv7f0qxgtt2lkzd2gzqjnuhmj9yzmpp270" // carol's address
|
||||
}
|
||||
|
||||
object MyWallet {
|
||||
const val name = "mine"
|
||||
val seedProvider =
|
||||
|
@ -43,9 +63,9 @@ enum class Servers(val host: String) {
|
|||
|
||||
// TODO: load most of these properties in later, perhaps from settings
|
||||
object SampleProperties {
|
||||
val COMPACT_BLOCK_SERVER = Servers.WLAN.host
|
||||
val COMPACT_BLOCK_SERVER = Servers.ZCASH_TESTNET.host
|
||||
const val COMPACT_BLOCK_PORT = 9067
|
||||
val wallet = AliceWallet
|
||||
val wallet = DaveWallet
|
||||
// TODO: placeholder until we have a network service for this
|
||||
val USD_PER_ZEC = BigDecimal("49.07", MathContext.DECIMAL128)
|
||||
}
|
|
@ -44,14 +44,16 @@ class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
|||
private val formatter = SimpleDateFormat("M/d h:mma", Locale.getDefault())
|
||||
|
||||
fun bind(tx: WalletTransaction) {
|
||||
val isHistory = icon != null
|
||||
val sign = if (tx.isSend) "-" else "+"
|
||||
val amountColor = if (tx.isSend) R.color.text_dark_dimmed else R.color.colorPrimary
|
||||
val transactionColor = if (tx.isSend) R.color.send_associated else R.color.receive_associated
|
||||
val transactionIcon = if (tx.isSend) R.drawable.ic_sent_transaction else R.drawable.ic_received_transaction
|
||||
val zecAbsoluteValue = tx.value.absoluteValue.convertZatoshiToZec(3)
|
||||
val zecAbsoluteValue = tx.value.absoluteValue.convertZatoshiToZec(6)
|
||||
val toOrFrom = if (tx.isSend) "to" else "from"
|
||||
val srcOrDestination = tx.address?.truncate() ?: "shielded mystery person"
|
||||
timestamp.text = if (!tx.isMined || tx.timeInSeconds == 0L) "Pending" else (tx.timeInSeconds * 1000L).toRelativeTimeString() //formatter.format(tx.timeInSeconds * 1000)
|
||||
timestamp.text = if (!tx.isMined || tx.timeInSeconds == 0L) "Pending"
|
||||
else (if (isHistory) formatter.format(tx.timeInSeconds * 1000) else (tx.timeInSeconds * 1000L).toRelativeTimeString())
|
||||
amount.text = "$sign$zecAbsoluteValue"
|
||||
amount.setTextColor(amountColor.toAppColor())
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ class SendFragment : BaseFragment(), SendPresenter.SendView, ScanFragment.Barcod
|
|||
binding.groupDialogSend.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun updateBalance(new: Long) {
|
||||
override fun updateAvailableBalance(new: Long) {
|
||||
// TODO: use a formatted string resource here
|
||||
val availableTextSpan = "${new.convertZatoshiToZecString(8)} $zec Available".toSpannable()
|
||||
availableTextSpan.setSpan(ForegroundColorSpan(R.color.colorPrimary.toAppColor()), availableTextSpan.length - "Available".length, availableTextSpan.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
|
|
@ -107,7 +107,8 @@ class WelcomeFragment : ProgressFragment(R.id.progress_welcome) {
|
|||
mainActivity?.navController?.navigate(
|
||||
destination,
|
||||
null,
|
||||
NavOptions.Builder().setPopUpTo(R.id.mobile_navigation, true).build(),
|
||||
null,
|
||||
// NavOptions.Builder().setPopUpTo(R.id.mobile_navigation, true).build(),
|
||||
extras
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cash.z.android.wallet.ui.fragment.HomeFragment
|
|||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||
import cash.z.wallet.sdk.data.*
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -46,12 +47,12 @@ class HomePresenter @Inject constructor(
|
|||
job?.cancel()?.also { job = null }
|
||||
}
|
||||
|
||||
private fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
||||
private fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Wallet.WalletBalance>) = launch {
|
||||
var old: Long? = null
|
||||
twig("balance binder starting!")
|
||||
for (new in channel) {
|
||||
twig("polled a balance item")
|
||||
bind(old, new).also { old = new }
|
||||
bind(old, new.total).also { old = new.total }
|
||||
}
|
||||
twig("balance binder exiting!")
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@ import cash.z.android.wallet.sample.SampleProperties
|
|||
import cash.z.android.wallet.ui.fragment.SendFragment
|
||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.data.Twig
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.ext.*
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -26,7 +27,7 @@ class SendPresenter @Inject constructor(
|
|||
) : Presenter {
|
||||
|
||||
interface SendView : PresenterView {
|
||||
fun updateBalance(new: Long)
|
||||
fun updateAvailableBalance(new: Long)
|
||||
fun setHeaders(isUsdSelected: Boolean, headerString: String, subheaderString: String)
|
||||
fun setHeaderValue(usdString: String)
|
||||
fun setSubheaderValue(usdString: String, isUsdSelected: Boolean)
|
||||
|
@ -75,7 +76,7 @@ class SendPresenter @Inject constructor(
|
|||
balanceJob?.cancel()?.also { balanceJob = null }
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
||||
fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Wallet.WalletBalance>) = launch {
|
||||
twig("send balance binder starting!")
|
||||
for (new in channel) {
|
||||
twig("send polled a balance item")
|
||||
|
@ -161,6 +162,8 @@ class SendPresenter @Inject constructor(
|
|||
|
||||
/**
|
||||
* Called when the user has completed their update to the header value, typically on focus change.
|
||||
*
|
||||
* @return true when the given amount is parsable, positive and less than the available amount.
|
||||
*/
|
||||
fun inputHeaderUpdated(amountString: String): Boolean {
|
||||
if (!validateAmount(amountString)) return false
|
||||
|
@ -188,18 +191,33 @@ class SendPresenter @Inject constructor(
|
|||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user has updated the toAddress, typically on focus change.
|
||||
*
|
||||
* @return true when the given address' length and content are valid
|
||||
*/
|
||||
fun inputAddressUpdated(newAddress: String): Boolean {
|
||||
if (!validateAddress(newAddress)) return false
|
||||
updateModel(sendUiModel.copy(toAddress = newAddress))
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user has updated the memo field, typically after pressing the 'done' key.
|
||||
*
|
||||
* @return true when the given memo's content does not contain invalid characters
|
||||
*/
|
||||
fun inputMemoUpdated(newMemo: String): Boolean {
|
||||
if (!validateMemo(newMemo)) return false
|
||||
updateModel(sendUiModel.copy(memo = newMemo))
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the user has pressed the send button and should be shown a confirmation dialog, next.
|
||||
*
|
||||
* @return true when all input fields contained valid data
|
||||
*/
|
||||
fun inputSendPressed(): Boolean {
|
||||
// double sanity check. Make sure view and model agree and are each valid and if not, highlight the error.
|
||||
if (!view.checkAllInput() || !validateAll()) return false
|
||||
|
@ -215,12 +233,12 @@ class SendPresenter @Inject constructor(
|
|||
return true
|
||||
}
|
||||
|
||||
fun bind(newZatoshiBalance: Long) {
|
||||
val available = newZatoshiBalance// - minersFee
|
||||
fun bind(balanceInfo: Wallet.WalletBalance) {
|
||||
val available = balanceInfo.available
|
||||
if (available >= 0) {
|
||||
twig("binding balance of $available")
|
||||
view.updateBalance(available)
|
||||
// updateModel(sendUiModel.copy(availableBalance = available))
|
||||
view.updateAvailableBalance(available)
|
||||
updateModel(sendUiModel.copy(availableBalance = available))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,12 +335,12 @@ class SendPresenter @Inject constructor(
|
|||
view.setAmountError("Please specify a larger amount")
|
||||
requiresValidation = true
|
||||
false
|
||||
// } else if (sendUiModel.availableBalance != null
|
||||
// && zatoshiValue >= sendUiModel.availableBalance!!) {
|
||||
// view.setAmountError("Exceeds available balance of " +
|
||||
// "${sendUiModel.availableBalance.convertZatoshiToZecString(3)}")
|
||||
// requiresValidation = true
|
||||
// false
|
||||
} else if (sendUiModel.availableBalance != null
|
||||
&& zatoshiValue >= sendUiModel.availableBalance!!) {
|
||||
view.setAmountError("Exceeds available balance of " +
|
||||
"${sendUiModel.availableBalance.convertZatoshiToZecString(3)}")
|
||||
requiresValidation = true
|
||||
false
|
||||
} else {
|
||||
view.setAmountError(null)
|
||||
true
|
||||
|
|
Loading…
Reference in New Issue