diff --git a/app/build.gradle b/app/build.gradle index 7a14477..1c44b4a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,9 +11,10 @@ apply plugin: 'com.google.firebase.firebase-perf' archivesBaseName = 'zcash-android-wallet' group = 'cash.z.ecc.android' -version = '1.0.0-alpha25' +version = '1.0.0-alpha28' android { + ndkVersion "21.1.6352462" compileSdkVersion Deps.compileSdkVersion buildToolsVersion Deps.buildToolsVersion viewBinding.enabled = true @@ -27,7 +28,6 @@ android { testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunnerArguments clearPackageData: 'true' multiDexEnabled true -// manifestPlaceholders = [rollbarToken: properties["rollbarToken"]] } flavorDimensions 'network' productFlavors { @@ -112,30 +112,40 @@ dependencies { implementation project(':feedback') implementation project(':mnemonic') implementation project(':lockbox') - implementation project(':sdk') implementation project(':chipsinputlayout') // Zcash - implementation 'com.github.zcash:zcash-android-wallet-plugins:1.0.0' - + implementation Deps.Zcash.ANDROID_WALLET_PLUGINS + zcashtestnetImplementation Deps.Zcash.Sdk.TESTNET + zcashmainnetImplementation Deps.Zcash.Sdk.MAINNET + // Kotlin implementation Deps.Kotlin.STDLIB // Android + implementation Deps.AndroidX.ANNOTATION implementation Deps.AndroidX.APPCOMPAT - implementation Deps.AndroidX.CORE_KTX implementation Deps.AndroidX.CONSTRAINT_LAYOUT - implementation Deps.AndroidX.Lifecycle.LIFECYCLE_RUNTIME_KTX + implementation Deps.AndroidX.CORE_KTX + implementation Deps.AndroidX.FRAGMENT_KTX + implementation Deps.AndroidX.LEGACY + implementation Deps.AndroidX.PAGING + implementation Deps.AndroidX.CameraX.CAMERA2 + implementation Deps.AndroidX.CameraX.CORE + implementation Deps.AndroidX.CameraX.LIFECYCLE + implementation Deps.AndroidX.CameraX.View.EXT + implementation Deps.AndroidX.CameraX.View.VIEW implementation Deps.AndroidX.Lifecycle.LIFECYCLE_EXTENSIONS + implementation Deps.AndroidX.Lifecycle.LIFECYCLE_RUNTIME_KTX implementation Deps.AndroidX.Navigation.FRAGMENT_KTX implementation Deps.AndroidX.Navigation.UI_KTX - implementation "androidx.room:room-ktx:2.2.3" - implementation "androidx.paging:paging-runtime-ktx:2.1.1" - implementation 'com.google.guava:guava:27.0.1-android' - kapt "androidx.room:room-compiler:2.2.3" + implementation Deps.AndroidX.Room.ROOM_KTX + kapt Deps.AndroidX.Room.ROOM_COMPILER // Google + implementation Deps.Google.GUAVA implementation Deps.Google.MATERIAL + implementation Deps.Google.ML_VISION // QR Scanner // Dagger implementation Deps.Dagger.ANDROID_SUPPORT @@ -143,44 +153,26 @@ dependencies { kapt Deps.Dagger.COMPILER // grpc-java - implementation "io.grpc:grpc-okhttp:1.25.0" - implementation "io.grpc:grpc-android:1.25.0" - implementation "io.grpc:grpc-protobuf-lite:1.25.0" - implementation "io.grpc:grpc-stub:1.25.0" - implementation 'javax.annotation:javax.annotation-api:1.3.2' - // solves error: Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-26.0-android.jar (com.google.guava:guava:26.0-android) and listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0) - // per this recommendation from Chris Povirk, given guava's decision to split ListenableFuture away from Guava: https://groups.google.com/d/msg/guava-discuss/GghaKwusjcY/bCIAKfzOEwAJ - implementation 'com.google.guava:guava:27.0.1-android' + implementation Deps.Grpc.ANDROID + implementation Deps.Grpc.OKHTTP + implementation Deps.Grpc.PROTOBUG + implementation Deps.Grpc.STUB + implementation Deps.JavaX.JAVA_ANNOTATION - // Analytics - implementation 'com.mixpanel.android:mixpanel-android:5.6.3' - implementation 'com.google.firebase:firebase-analytics:17.2.2' - implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' - implementation 'com.crashlytics.sdk.android:crashlytics-ndk:2.1.1' - implementation 'com.google.firebase:firebase-perf:19.0.5' - - // QR Scanning - implementation 'com.google.firebase:firebase-ml-vision:24.0.1' - implementation 'androidx.camera:camera-core:1.0.0-alpha10' - implementation 'androidx.camera:camera-camera2:1.0.0-alpha10' - implementation "androidx.camera:camera-view:1.0.0-alpha07" - implementation "androidx.camera:camera-extensions:1.0.0-alpha07" - implementation "androidx.camera:camera-lifecycle:1.0.0-alpha10" + // Analytics (for dogfooding/crash-reporting/feedback only on internal team builds) + implementation Deps.Analytics.CRASHLYTICS + implementation Deps.Analytics.CRASHLYTICS_NDK + implementation Deps.Analytics.FIREBASE + implementation Deps.Analytics.FIREBASE_PERF + implementation Deps.Analytics.MIXPANEL // Misc. - implementation 'com.airbnb.android:lottie:3.1.0' - implementation 'com.facebook.stetho:stetho:1.5.1' - // check for build errors at https://jitpack.io/com/github/gmale/chips-input-layout//build.log -// implementation 'com.github.gmale:chips-input-layout:4750760a7222bc04ca48266b387456d2b03541a7' - - implementation 'androidx.annotation:annotation:1.1.0' + implementation Deps.Misc.LOTTIE // Tests - - implementation 'androidx.legacy:legacy-support-v4:1.0.0' + testImplementation Deps.Test.COROUTINES_TEST testImplementation Deps.Test.JUNIT - testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.3' + testImplementation Deps.Test.MOKITO androidTestImplementation Deps.Test.Android.JUNIT androidTestImplementation Deps.Test.Android.ESPRESSO } diff --git a/app/src/androidTest/java/cash/z/ecc/android/integration/IntegrationTest.kt b/app/src/androidTest/java/cash/z/ecc/android/integration/IntegrationTest.kt index c60373f..9425ef7 100644 --- a/app/src/androidTest/java/cash/z/ecc/android/integration/IntegrationTest.kt +++ b/app/src/androidTest/java/cash/z/ecc/android/integration/IntegrationTest.kt @@ -5,7 +5,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import cash.z.ecc.android.lockbox.LockBox import cash.z.ecc.kotlin.mnemonic.Mnemonics -import cash.z.wallet.sdk.Initializer +import cash.z.ecc.android.sdk.Initializer import okio.Buffer import okio.GzipSink import okio.Okio diff --git a/app/src/main/java/cash/z/ecc/android/ZcashWalletApp.kt b/app/src/main/java/cash/z/ecc/android/ZcashWalletApp.kt index 809014c..fc3ab61 100644 --- a/app/src/main/java/cash/z/ecc/android/ZcashWalletApp.kt +++ b/app/src/main/java/cash/z/ecc/android/ZcashWalletApp.kt @@ -8,10 +8,10 @@ import androidx.camera.core.CameraXConfig import cash.z.ecc.android.di.component.AppComponent import cash.z.ecc.android.di.component.DaggerAppComponent import cash.z.ecc.android.feedback.FeedbackCoordinator -import cash.z.wallet.sdk.ext.SilentTwig -import cash.z.wallet.sdk.ext.TroubleshootingTwig -import cash.z.wallet.sdk.ext.Twig -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.SilentTwig +import cash.z.ecc.android.sdk.ext.TroubleshootingTwig +import cash.z.ecc.android.sdk.ext.Twig +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.* import javax.inject.Inject diff --git a/app/src/main/java/cash/z/ecc/android/di/component/InitializerSubcomponent.kt b/app/src/main/java/cash/z/ecc/android/di/component/InitializerSubcomponent.kt index 0e8b8e8..5212d3a 100644 --- a/app/src/main/java/cash/z/ecc/android/di/component/InitializerSubcomponent.kt +++ b/app/src/main/java/cash/z/ecc/android/di/component/InitializerSubcomponent.kt @@ -4,7 +4,7 @@ import cash.z.ecc.android.ZcashWalletApp import cash.z.ecc.android.di.annotation.ActivityScope import cash.z.ecc.android.di.annotation.SynchronizerScope import cash.z.ecc.android.di.module.InitializerModule -import cash.z.wallet.sdk.Initializer +import cash.z.ecc.android.sdk.Initializer import dagger.BindsInstance import dagger.Subcomponent diff --git a/app/src/main/java/cash/z/ecc/android/di/component/SynchronizerSubcomponent.kt b/app/src/main/java/cash/z/ecc/android/di/component/SynchronizerSubcomponent.kt index ef7c602..8c4f2b6 100644 --- a/app/src/main/java/cash/z/ecc/android/di/component/SynchronizerSubcomponent.kt +++ b/app/src/main/java/cash/z/ecc/android/di/component/SynchronizerSubcomponent.kt @@ -3,8 +3,8 @@ package cash.z.ecc.android.di.component import androidx.lifecycle.ViewModelProvider import cash.z.ecc.android.di.annotation.SynchronizerScope import cash.z.ecc.android.di.module.SynchronizerModule -import cash.z.wallet.sdk.Initializer -import cash.z.wallet.sdk.Synchronizer +import cash.z.ecc.android.sdk.Initializer +import cash.z.ecc.android.sdk.Synchronizer import dagger.BindsInstance import dagger.Subcomponent import javax.inject.Named diff --git a/app/src/main/java/cash/z/ecc/android/di/module/InitializerModule.kt b/app/src/main/java/cash/z/ecc/android/di/module/InitializerModule.kt index 4c605e3..aa21008 100644 --- a/app/src/main/java/cash/z/ecc/android/di/module/InitializerModule.kt +++ b/app/src/main/java/cash/z/ecc/android/di/module/InitializerModule.kt @@ -1,7 +1,7 @@ package cash.z.ecc.android.di.module import android.content.Context -import cash.z.wallet.sdk.Initializer +import cash.z.ecc.android.sdk.Initializer import dagger.Module import dagger.Provides import dagger.Reusable diff --git a/app/src/main/java/cash/z/ecc/android/di/module/SynchronizerModule.kt b/app/src/main/java/cash/z/ecc/android/di/module/SynchronizerModule.kt index 8af5e00..93248d9 100644 --- a/app/src/main/java/cash/z/ecc/android/di/module/SynchronizerModule.kt +++ b/app/src/main/java/cash/z/ecc/android/di/module/SynchronizerModule.kt @@ -2,8 +2,8 @@ package cash.z.ecc.android.di.module import android.content.Context import cash.z.ecc.android.di.annotation.SynchronizerScope -import cash.z.wallet.sdk.Initializer -import cash.z.wallet.sdk.Synchronizer +import cash.z.ecc.android.sdk.Initializer +import cash.z.ecc.android.sdk.Synchronizer import dagger.Module import dagger.Provides diff --git a/app/src/main/java/cash/z/ecc/android/ext/Dialogs.kt b/app/src/main/java/cash/z/ecc/android/ext/Dialogs.kt new file mode 100644 index 0000000..27f6f84 --- /dev/null +++ b/app/src/main/java/cash/z/ecc/android/ext/Dialogs.kt @@ -0,0 +1,85 @@ +package cash.z.ecc.android.ext + +import android.app.ActivityManager +import android.app.Dialog +import android.content.Context +import android.content.Intent +import android.provider.Settings +import androidx.core.content.getSystemService +import com.google.android.material.dialog.MaterialAlertDialogBuilder + + +fun Context.showClearDataConfirmation(onDismiss: () -> Unit = {}, onCancel: () -> Unit = {}): Dialog { + return MaterialAlertDialogBuilder(this) + .setTitle("Nuke Wallet?") + .setMessage("WARNING: Potential Loss of Funds\n\nClearing all wallet data and can result in a loss of funds, if you cannot locate your correct seed phrase.\n\nPlease confirm that you have your 24-word seed phrase available before proceeding.") + .setCancelable(false) + .setPositiveButton("Cancel") { dialog, _ -> + dialog.dismiss() + onDismiss() + onCancel() + } + .setNegativeButton("Erase Wallet") { dialog, _ -> + dialog.dismiss() + onDismiss() + getSystemService()?.clearApplicationUserData() + } + .show() +} + +fun Context.showUninitializedError(error: Throwable? = null, onDismiss: () -> Unit = {}): Dialog { + return MaterialAlertDialogBuilder(this) + .setTitle("Wallet Improperly Initialized") + .setMessage("This wallet has not been initialized correctly! Perhaps an error occurred during install.\n\nThis can be fixed with a reset. First, locate your backup seed phrase, then CLEAR DATA and reimport it.") + .setCancelable(false) + .setPositiveButton("Exit") { dialog, _ -> + dialog.dismiss() + onDismiss() + if (error != null) throw error + } + .setNegativeButton("Clear Data") { dialog, _ -> + showClearDataConfirmation(onDismiss, onCancel = { + // do not let the user back into the app because we cannot recover from this case + showUninitializedError(error, onDismiss) + }) + } + .show() +} + +fun Context.showScanFailure(error: Throwable?, onCancel: () -> Unit = {}, onDismiss: () -> Unit = {}): Dialog { + val message = if (error == null) { + "Unknown error" + } else { + "${error.message}${if (error.cause != null) "\n\nCaused by: ${error.cause}" else ""}" + } + return MaterialAlertDialogBuilder(this) + .setTitle("Scan Failure") + .setMessage(message) + .setCancelable(true) + .setPositiveButton("Retry") { d, _ -> + d.dismiss() + onDismiss() + } + .setNegativeButton("Ignore") { d, _ -> + d.dismiss() + onCancel() + onDismiss() + } + .show() +} + +fun Context.showCriticalProcessorError(error: Throwable?, onRetry: () -> Unit = {}): Dialog { + return MaterialAlertDialogBuilder(this) + .setTitle("Processor Error") + .setMessage(error?.message ?: "Critical error while processing blocks!") + .setCancelable(false) + .setPositiveButton("Retry") { d, _ -> + d.dismiss() + onRetry() + } + .setNegativeButton("Exit") { dialog, _ -> + dialog.dismiss() + throw error ?: RuntimeException("Critical error while processing blocks and the user chose to exit.") + } + .show() +} \ No newline at end of file diff --git a/app/src/main/java/cash/z/ecc/android/ext/EditText.kt b/app/src/main/java/cash/z/ecc/android/ext/EditText.kt index 24d6064..adba13b 100644 --- a/app/src/main/java/cash/z/ecc/android/ext/EditText.kt +++ b/app/src/main/java/cash/z/ecc/android/ext/EditText.kt @@ -3,9 +3,9 @@ package cash.z.ecc.android.ext import android.view.inputmethod.EditorInfo.IME_ACTION_DONE import android.widget.EditText import android.widget.TextView -import cash.z.wallet.sdk.ext.convertZecToZatoshi -import cash.z.wallet.sdk.ext.safelyConvertToBigDecimal -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.convertZecToZatoshi +import cash.z.ecc.android.sdk.ext.safelyConvertToBigDecimal +import cash.z.ecc.android.sdk.ext.twig fun EditText.onEditorActionDone(block: (EditText) -> Unit) { this.setOnEditorActionListener { _, actionId, _ -> diff --git a/app/src/main/java/cash/z/ecc/android/ui/MainActivity.kt b/app/src/main/java/cash/z/ecc/android/ui/MainActivity.kt index d46ab6e..617a007 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/MainActivity.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/MainActivity.kt @@ -38,10 +38,10 @@ import cash.z.ecc.android.feedback.Report.Error.NonFatal.Reorg import cash.z.ecc.android.feedback.Report.NonUserAction.FEEDBACK_STOPPED import cash.z.ecc.android.feedback.Report.NonUserAction.SYNC_START import cash.z.ecc.android.feedback.Report.Tap.COPY_ADDRESS -import cash.z.wallet.sdk.Initializer -import cash.z.wallet.sdk.exception.CompactBlockProcessorException -import cash.z.wallet.sdk.ext.ZcashSdk -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Initializer +import cash.z.ecc.android.sdk.exception.CompactBlockProcessorException +import cash.z.ecc.android.sdk.ext.ZcashSdk +import cash.z.ecc.android.sdk.ext.twig import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.launch diff --git a/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionAdapter.kt b/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionAdapter.kt index 22aa563..ad12b56 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionAdapter.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionAdapter.kt @@ -5,7 +5,7 @@ import android.view.ViewGroup import androidx.paging.PagedListAdapter import androidx.recyclerview.widget.DiffUtil import cash.z.ecc.android.R -import cash.z.wallet.sdk.entity.ConfirmedTransaction +import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction class TransactionAdapter : PagedListAdapter>( diff --git a/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionViewHolder.kt b/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionViewHolder.kt index 3bca6c7..9494555 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionViewHolder.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/detail/TransactionViewHolder.kt @@ -11,8 +11,8 @@ import cash.z.ecc.android.ui.MainActivity import cash.z.ecc.android.ui.send.SendViewModel import cash.z.ecc.android.ui.util.INCLUDE_MEMO_PREFIX import cash.z.ecc.android.ui.util.toUtf8Memo -import cash.z.wallet.sdk.entity.ConfirmedTransaction -import cash.z.wallet.sdk.ext.* +import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction +import cash.z.ecc.android.sdk.ext.* import com.google.android.material.dialog.MaterialAlertDialogBuilder import java.nio.charset.Charset import java.text.SimpleDateFormat diff --git a/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailFragment.kt index 9305458..8595cb3 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailFragment.kt @@ -15,12 +15,12 @@ import cash.z.ecc.android.ext.toColoredSpan import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Tap.DETAIL_BACK import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.block.CompactBlockProcessor.WalletBalance -import cash.z.wallet.sdk.entity.ConfirmedTransaction -import cash.z.wallet.sdk.ext.collectWith -import cash.z.wallet.sdk.ext.convertZatoshiToZecString -import cash.z.wallet.sdk.ext.toAbbreviatedAddress -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.block.CompactBlockProcessor.WalletBalance +import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction +import cash.z.ecc.android.sdk.ext.collectWith +import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.launch diff --git a/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailViewModel.kt index 09f965a..ffdd2d0 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/detail/WalletDetailViewModel.kt @@ -1,8 +1,8 @@ package cash.z.ecc.android.ui.detail import androidx.lifecycle.ViewModel -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.ext.twig import javax.inject.Inject class WalletDetailViewModel @Inject constructor() : ViewModel() { diff --git a/app/src/main/java/cash/z/ecc/android/ui/home/HomeFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/home/HomeFragment.kt index 078a376..731446e 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/home/HomeFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/home/HomeFragment.kt @@ -18,13 +18,13 @@ import cash.z.ecc.android.ui.home.HomeFragment.BannerAction.* import cash.z.ecc.android.ui.send.SendViewModel import cash.z.ecc.android.ui.setup.WalletSetupViewModel import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.NO_SEED -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.Synchronizer.Status.* -import cash.z.wallet.sdk.block.CompactBlockProcessor -import cash.z.wallet.sdk.ext.convertZatoshiToZecString -import cash.z.wallet.sdk.ext.convertZecToZatoshi -import cash.z.wallet.sdk.ext.safelyConvertToBigDecimal -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.Synchronizer.Status.* +import cash.z.ecc.android.sdk.block.CompactBlockProcessor +import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.ext.convertZecToZatoshi +import cash.z.ecc.android.sdk.ext.safelyConvertToBigDecimal +import cash.z.ecc.android.sdk.ext.twig import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* diff --git a/app/src/main/java/cash/z/ecc/android/ui/home/HomeViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/home/HomeViewModel.kt index 63395be..5e0dfec 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/home/HomeViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/home/HomeViewModel.kt @@ -1,14 +1,14 @@ package cash.z.ecc.android.ui.home import androidx.lifecycle.ViewModel -import cash.z.wallet.sdk.SdkSynchronizer -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.Synchronizer.Status.* -import cash.z.wallet.sdk.block.CompactBlockProcessor -import cash.z.wallet.sdk.exception.RustLayerException -import cash.z.wallet.sdk.ext.ZcashSdk.MINERS_FEE_ZATOSHI -import cash.z.wallet.sdk.ext.ZcashSdk.ZATOSHI_PER_ZEC -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.SdkSynchronizer +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.Synchronizer.Status.* +import cash.z.ecc.android.sdk.block.CompactBlockProcessor +import cash.z.ecc.android.sdk.exception.RustLayerException +import cash.z.ecc.android.sdk.ext.ZcashSdk.MINERS_FEE_ZATOSHI +import cash.z.ecc.android.sdk.ext.ZcashSdk.ZATOSHI_PER_ZEC +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.channels.ConflatedBroadcastChannel import kotlinx.coroutines.flow.* import javax.inject.Inject diff --git a/app/src/main/java/cash/z/ecc/android/ui/home/MagicSnakeLoader.kt b/app/src/main/java/cash/z/ecc/android/ui/home/MagicSnakeLoader.kt index 57f812e..a9514c7 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/home/MagicSnakeLoader.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/home/MagicSnakeLoader.kt @@ -1,7 +1,7 @@ package cash.z.ecc.android.ui.home import android.animation.ValueAnimator -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.twig import com.airbnb.lottie.LottieAnimationView class MagicSnakeLoader( diff --git a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt index 4d4088a..2d64156 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt @@ -19,8 +19,8 @@ import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Funnel.UserFeedback import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.ext.toAbbreviatedAddress -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.launch import okio.Okio import java.io.File diff --git a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileViewModel.kt index 5b8e351..2745a9e 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileViewModel.kt @@ -1,8 +1,8 @@ package cash.z.ecc.android.ui.profile import androidx.lifecycle.ViewModel -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.ext.twig import javax.inject.Inject class ProfileViewModel @Inject constructor() : ViewModel() { diff --git a/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveFragment.kt index 68777c4..9524f6a 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveFragment.kt @@ -13,8 +13,8 @@ import cash.z.ecc.android.ext.onClickNavTo import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.ext.toAbbreviatedAddress -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.launch import kotlin.math.roundToInt diff --git a/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveViewModel.kt index 1b4cfbc..0eecafc 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/receive/ReceiveViewModel.kt @@ -1,8 +1,8 @@ package cash.z.ecc.android.ui.receive import androidx.lifecycle.ViewModel -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.ext.twig import javax.inject.Inject class ReceiveViewModel @Inject constructor() : ViewModel() { diff --git a/app/src/main/java/cash/z/ecc/android/ui/scan/QrAnalyzer.kt b/app/src/main/java/cash/z/ecc/android/ui/scan/QrAnalyzer.kt index c13ab4e..fbb5de4 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/scan/QrAnalyzer.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/scan/QrAnalyzer.kt @@ -2,9 +2,9 @@ package cash.z.ecc.android.ui.scan import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageProxy -import cash.z.wallet.sdk.ext.retrySimple -import cash.z.wallet.sdk.ext.retryUpTo -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.retrySimple +import cash.z.ecc.android.sdk.ext.retryUpTo +import cash.z.ecc.android.sdk.ext.twig import com.google.android.gms.tasks.Task import com.google.firebase.ml.vision.FirebaseVision import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode diff --git a/app/src/main/java/cash/z/ecc/android/ui/scan/ScanFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/scan/ScanFragment.kt index 8317e1b..67d22c6 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/scan/ScanFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/scan/ScanFragment.kt @@ -3,12 +3,10 @@ package cash.z.ecc.android.ui.scan import android.content.Context import android.content.pm.PackageManager import android.os.Bundle +import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.View -import androidx.camera.core.CameraSelector -import androidx.camera.core.ImageAnalysis -import androidx.camera.core.ImageProxy -import androidx.camera.core.Preview +import androidx.camera.core.* import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat import cash.z.ecc.android.R @@ -18,11 +16,15 @@ import cash.z.ecc.android.di.viewmodel.viewModel import cash.z.ecc.android.ext.onClickNavBack import cash.z.ecc.android.ext.onClickNavTo import cash.z.ecc.android.feedback.Report -import cash.z.ecc.android.feedback.Report.Tap.* +import cash.z.ecc.android.feedback.Report.Tap.SCAN_BACK +import cash.z.ecc.android.feedback.Report.Tap.SCAN_RECEIVE +import cash.z.ecc.android.sdk.ext.twig import cash.z.ecc.android.ui.base.BaseFragment import cash.z.ecc.android.ui.send.SendViewModel +import com.crashlytics.android.Crashlytics import com.google.common.util.concurrent.ListenableFuture import kotlinx.coroutines.launch +import java.util.concurrent.ExecutorService import java.util.concurrent.Executors class ScanFragment : BaseFragment() { @@ -33,11 +35,15 @@ class ScanFragment : BaseFragment() { private lateinit var cameraProviderFuture: ListenableFuture + private var cameraExecutor: ExecutorService? = null + override fun inflate(inflater: LayoutInflater): FragmentScanBinding = FragmentScanBinding.inflate(inflater) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + if (cameraExecutor != null) cameraExecutor?.shutdown() + cameraExecutor = Executors.newSingleThreadExecutor() binding.buttonReceive.onClickNavTo(R.id.action_nav_scan_to_nav_receive) { tapped(SCAN_RECEIVE) } binding.backButtonHitArea.onClickNavBack() { tapped(SCAN_BACK) } @@ -56,26 +62,67 @@ class ScanFragment : BaseFragment() { }, ContextCompat.getMainExecutor(context)) } + override fun onDestroyView() { + super.onDestroyView() + cameraExecutor?.shutdown() + cameraExecutor = null + } + private fun bindPreview(cameraProvider: ProcessCameraProvider) { - Preview.Builder().setTargetName("Preview").build().let { preview -> - preview.setSurfaceProvider(binding.preview.previewSurfaceProvider) + // Most of the code here is adapted from: https://github.com/android/camera-samples/blob/master/CameraXBasic/app/src/main/java/com/android/example/cameraxbasic/fragments/CameraFragment.kt + // it's worth keeping tabs on that implementation because they keep making breaking changes to these APIs! - val cameraSelector = CameraSelector.Builder() - .requireLensFacing(CameraSelector.LENS_FACING_BACK) - .build() + // Get screen metrics used to setup camera for full screen resolution + val metrics = DisplayMetrics().also { binding.preview.display.getRealMetrics(it) } + val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels) + val rotation = binding.preview.display.rotation - val imageAnalysis = ImageAnalysis.Builder() - .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) - .build() + val preview = + Preview.Builder().setTargetName("Preview").setTargetAspectRatio(screenAspectRatio) + .setTargetRotation(rotation).build() - imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), QrAnalyzer { q, i -> - onQrScanned(q, i) - }) + val cameraSelector = CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build() + + val imageAnalysis = ImageAnalysis.Builder().setTargetAspectRatio(screenAspectRatio) + .setTargetRotation(rotation) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build() + + imageAnalysis.setAnalyzer(cameraExecutor!!, QrAnalyzer { q, i -> + onQrScanned(q, i) + }) + + // Must unbind the use-cases before rebinding them + cameraProvider.unbindAll() + + try { cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis) + preview.setSurfaceProvider(binding.preview.createSurfaceProvider()) + } catch (t: Throwable) { + // TODO: consider bubbling this up to the user + Crashlytics.logException(t) + twig("Error while opening the camera: $t") } } + /** + * Adapted from: https://github.com/android/camera-samples/blob/master/CameraXBasic/app/src/main/java/com/android/example/cameraxbasic/fragments/CameraFragment.kt#L350 + */ + private fun aspectRatio(width: Int, height: Int): Int { + val previewRatio = kotlin.math.max(width, height).toDouble() / kotlin.math.min( + width, + height + ) + if (kotlin.math.abs(previewRatio - (4.0 / 3.0)) + <= kotlin.math.abs(previewRatio - (16.0 / 9.0))) { + return AspectRatio.RATIO_4_3 + } + return AspectRatio.RATIO_16_9 + } + private fun onQrScanned(qrContent: String, image: ImageProxy) { resumedScope.launch { if (viewModel.isNotValid(qrContent)) image.close() // continue scanning diff --git a/app/src/main/java/cash/z/ecc/android/ui/scan/ScanViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/scan/ScanViewModel.kt index b6746d0..4fe988e 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/scan/ScanViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/scan/ScanViewModel.kt @@ -1,8 +1,8 @@ package cash.z.ecc.android.ui.scan import androidx.lifecycle.ViewModel -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.ext.twig import javax.inject.Inject class ScanViewModel @Inject constructor() : ViewModel() { diff --git a/app/src/main/java/cash/z/ecc/android/ui/send/SendAddressFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/send/SendAddressFragment.kt index d8a9526..db9c2a2 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/send/SendAddressFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/send/SendAddressFragment.kt @@ -16,9 +16,10 @@ import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Funnel.Send import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.block.CompactBlockProcessor.WalletBalance -import cash.z.wallet.sdk.ext.* +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.block.CompactBlockProcessor.WalletBalance +import cash.z.ecc.android.sdk.ext.* +import cash.z.ecc.android.sdk.validate.AddressType import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -85,9 +86,9 @@ class SendAddressFragment : BaseFragment(), private fun onAddressChanged(address: String) { resumedScope.launch { var type = when (sendViewModel.validateAddress(address)) { - is Synchronizer.AddressType.Transparent -> "This is a valid transparent address" to R.color.zcashGreen - is Synchronizer.AddressType.Shielded -> "This is a valid shielded address" to R.color.zcashGreen - is Synchronizer.AddressType.Invalid -> "This address appears to be invalid" to R.color.zcashRed + is AddressType.Transparent -> "This is a valid transparent address" to R.color.zcashGreen + is AddressType.Shielded -> "This is a valid shielded address" to R.color.zcashGreen + is AddressType.Invalid -> "This address appears to be invalid" to R.color.zcashRed } if (address == sendViewModel.synchronizer.getAddress()) type = "Warning, this appears to be your address!" to R.color.zcashRed diff --git a/app/src/main/java/cash/z/ecc/android/ui/send/SendConfirmFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/send/SendConfirmFragment.kt index eca5e2d..73d6fea 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/send/SendConfirmFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/send/SendConfirmFragment.kt @@ -13,8 +13,8 @@ import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Funnel.Send import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.ext.toAbbreviatedAddress -import cash.z.wallet.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress +import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString import kotlinx.coroutines.launch class SendConfirmFragment : BaseFragment() { diff --git a/app/src/main/java/cash/z/ecc/android/ui/send/SendFinalFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/send/SendFinalFragment.kt index f275f2d..814c6b1 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/send/SendFinalFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/send/SendFinalFragment.kt @@ -12,10 +12,10 @@ import cash.z.ecc.android.ext.goneIf import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.entity.* -import cash.z.wallet.sdk.ext.convertZatoshiToZecString -import cash.z.wallet.sdk.ext.toAbbreviatedAddress -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.db.entity.* +import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress +import cash.z.ecc.android.sdk.ext.twig import com.crashlytics.android.Crashlytics import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow diff --git a/app/src/main/java/cash/z/ecc/android/ui/send/SendViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/send/SendViewModel.kt index f75cd51..9756f4b 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/send/SendViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/send/SendViewModel.kt @@ -14,12 +14,13 @@ import cash.z.ecc.android.feedback.Report.MetricType.* import cash.z.ecc.android.lockbox.LockBox import cash.z.ecc.android.ui.setup.WalletSetupViewModel import cash.z.ecc.android.ui.util.INCLUDE_MEMO_PREFIX -import cash.z.wallet.sdk.Initializer -import cash.z.wallet.sdk.Synchronizer -import cash.z.wallet.sdk.entity.* -import cash.z.wallet.sdk.ext.ZcashSdk -import cash.z.wallet.sdk.ext.convertZatoshiToZecString -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Initializer +import cash.z.ecc.android.sdk.Synchronizer +import cash.z.ecc.android.sdk.db.entity.* +import cash.z.ecc.android.sdk.ext.ZcashSdk +import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString +import cash.z.ecc.android.sdk.ext.twig +import cash.z.ecc.android.sdk.validate.AddressType import com.crashlytics.android.Crashlytics import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.flow.Flow @@ -94,7 +95,7 @@ class SendViewModel @Inject constructor() : ViewModel() { } } - suspend fun validateAddress(address: String): Synchronizer.AddressType = + suspend fun validateAddress(address: String): AddressType = synchronizer.validateAddress(address) fun validate(maxZatoshi: Long?) = flow { diff --git a/app/src/main/java/cash/z/ecc/android/ui/setup/LandingFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/setup/LandingFragment.kt index c3d743f..491486e 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/setup/LandingFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/setup/LandingFragment.kt @@ -18,7 +18,7 @@ import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.SEED_WITHOUT_BACKUP import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.SEED_WITH_BACKUP -import cash.z.wallet.sdk.Initializer +import cash.z.ecc.android.sdk.Initializer import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/app/src/main/java/cash/z/ecc/android/ui/setup/RestoreFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/setup/RestoreFragment.kt index 9011f97..389d4ad 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/setup/RestoreFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/setup/RestoreFragment.kt @@ -21,8 +21,8 @@ import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Funnel.Restore import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment -import cash.z.wallet.sdk.ext.ZcashSdk -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.ZcashSdk +import cash.z.ecc.android.sdk.ext.twig import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.tylersuehr.chips.Chip import com.tylersuehr.chips.ChipsAdapter diff --git a/app/src/main/java/cash/z/ecc/android/ui/setup/SeedWordAdapter.kt b/app/src/main/java/cash/z/ecc/android/ui/setup/SeedWordAdapter.kt index 26b0057..fe12c6a 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/setup/SeedWordAdapter.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/setup/SeedWordAdapter.kt @@ -11,7 +11,7 @@ import cash.z.ecc.android.feedback.Report import cash.z.ecc.android.feedback.Report.Funnel.Restore import cash.z.ecc.android.ui.MainActivity import cash.z.ecc.android.ui.setup.SeedWordChip -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.ext.twig class SeedWordAdapter : ChipsAdapter { diff --git a/app/src/main/java/cash/z/ecc/android/ui/setup/WalletSetupViewModel.kt b/app/src/main/java/cash/z/ecc/android/ui/setup/WalletSetupViewModel.kt index a875919..8d8a626 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/setup/WalletSetupViewModel.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/setup/WalletSetupViewModel.kt @@ -8,11 +8,11 @@ import cash.z.ecc.android.feedback.measure import cash.z.ecc.android.lockbox.LockBox import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.* import cash.z.ecc.kotlin.mnemonic.Mnemonics -import cash.z.wallet.sdk.Initializer -import cash.z.wallet.sdk.Initializer.DefaultBirthdayStore -import cash.z.wallet.sdk.Initializer.DefaultBirthdayStore.Companion.ImportedWalletBirthdayStore -import cash.z.wallet.sdk.Initializer.DefaultBirthdayStore.Companion.NewWalletBirthdayStore -import cash.z.wallet.sdk.ext.twig +import cash.z.ecc.android.sdk.Initializer +import cash.z.ecc.android.sdk.Initializer.DefaultBirthdayStore +import cash.z.ecc.android.sdk.Initializer.DefaultBirthdayStore.Companion.ImportedWalletBirthdayStore +import cash.z.ecc.android.sdk.Initializer.DefaultBirthdayStore.Companion.NewWalletBirthdayStore +import cash.z.ecc.android.sdk.ext.twig import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow diff --git a/app/src/test/java/cash/z/ecc/android/SendViewModelTest.kt b/app/src/test/java/cash/z/ecc/android/SendViewModelTest.kt index db6a34d..a6be8f8 100644 --- a/app/src/test/java/cash/z/ecc/android/SendViewModelTest.kt +++ b/app/src/test/java/cash/z/ecc/android/SendViewModelTest.kt @@ -2,7 +2,7 @@ package cash.z.ecc.android import cash.z.ecc.android.feedback.Feedback import cash.z.ecc.android.ui.send.SendViewModel -import cash.z.wallet.sdk.entity.* +import cash.z.ecc.android.sdk.entity.* import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyZeroInteractions import com.nhaarman.mockitokotlin2.whenever diff --git a/build.gradle b/build.gradle index 5385374..7584f5d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,6 @@ import cash.z.ecc.android.Deps buildscript { - ext { - kotlin_version = '1.3.61' - } repositories { google() jcenter() @@ -12,7 +9,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.6.0-rc02' + classpath 'com.android.tools.build:gradle:4.0.0' classpath 'com.google.gms:google-services:4.3.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}" classpath 'io.fabric.tools:gradle:1.31.2' diff --git a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt index f21ec55..0642076 100644 --- a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt +++ b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt @@ -3,7 +3,7 @@ package cash.z.ecc.android object Deps { // For use in the top-level build.gradle which gives an error when provided // `Deps.Kotlin.version` directly - const val kotlinVersion = "1.3.61" + const val kotlinVersion = "1.3.72" const val compileSdkVersion = 29 const val buildToolsVersion = "29.0.2" @@ -11,18 +11,34 @@ object Deps { const val targetSdkVersion = 29 object AndroidX { + const val ANNOTATION = "androidx.annotation:annotation:1.1.0" const val APPCOMPAT = "androidx.appcompat:appcompat:1.1.0" - const val CORE_KTX = "androidx.core:core-ktx:1.1.0" const val CONSTRAINT_LAYOUT = "androidx.constraintlayout:constraintlayout:1.1.3" + const val CORE_KTX = "androidx.core:core-ktx:1.1.0" const val FRAGMENT_KTX = "androidx.fragment:fragment-ktx:1.1.0-beta01" + const val LEGACY = "androidx.legacy:legacy-support-v4:1.0.0" const val MULTIDEX = "androidx.multidex:multidex:2.0.1" + const val PAGING = "androidx.paging:paging-runtime-ktx:2.1.2" + object CameraX : Version("1.0.0-beta04") { + val CAMERA2 = "androidx.camera:camera-camera2:1.0.0-beta04" + val CORE = "androidx.camera:camera-core:1.0.0-beta04" + val LIFECYCLE = "androidx.camera:camera-lifecycle:1.0.0-beta04" + object View : Version("1.0.0-alpha11") { + val EXT = "androidx.camera:camera-extensions:1.0.0-alpha11" + val VIEW = "androidx.camera:camera-view:1.0.0-alpha11" + } + } + object Lifecycle : Version("2.2.0-rc02") { + val LIFECYCLE_RUNTIME_KTX = "androidx.lifecycle:lifecycle-runtime-ktx:$version" + val LIFECYCLE_EXTENSIONS = "androidx.lifecycle:lifecycle-extensions:$version" + } object Navigation : Version("2.2.0") { val FRAGMENT_KTX = "androidx.navigation:navigation-fragment-ktx:$version" val UI_KTX = "androidx.navigation:navigation-ui-ktx:$version" } - object Lifecycle: Version("2.2.0-rc02") { - val LIFECYCLE_RUNTIME_KTX = "androidx.lifecycle:lifecycle-runtime-ktx:$version" - val LIFECYCLE_EXTENSIONS = "androidx.lifecycle:lifecycle-extensions:$version" + object Room : Version("2.2.5") { + val ROOM_COMPILER = "androidx.room:room-compiler:$version" + val ROOM_KTX = "androidx.room:room-ktx:$version" } } object Dagger : Version("2.25.2") { @@ -31,35 +47,61 @@ object Deps { val COMPILER = "com.google.dagger:dagger-compiler:$version" } object Google { + // solves error: Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-26.0-android.jar (com.google.guava:guava:26.0-android) and listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0) + // per this recommendation from Chris Povirk, given guava's decision to split ListenableFuture away from Guava: https://groups.google.com/d/msg/guava-discuss/GghaKwusjcY/bCIAKfzOEwAJ + const val GUAVA = "com.google.guava:guava:27.0.1-android" const val MATERIAL = "com.google.android.material:material:1.1.0-beta01" + // QR Scanner + const val ML_VISION = "com.google.firebase:firebase-ml-vision:24.0.3" + } + object Grpc : Version("1.25.0") { + val ANDROID = "io.grpc:grpc-android:$version" + val OKHTTP = "io.grpc:grpc-okhttp:$version" + val PROTOBUG = "io.grpc:grpc-protobuf-lite:$version" + val STUB = "io.grpc:grpc-stub:$version" + } + object Analytics { // for dogfooding/crash-reporting/feedback only on internal team builds + val CRASHLYTICS = "com.crashlytics.sdk.android:crashlytics:2.10.1" + val CRASHLYTICS_NDK = "com.crashlytics.sdk.android:crashlytics-ndk:2.1.1" + val FIREBASE = "com.google.firebase:firebase-analytics:17.4.3" + val FIREBASE_PERF = "com.google.firebase:firebase-perf:19.0.7" + val MIXPANEL = "com.mixpanel.android:mixpanel-android:5.6.3" } object JavaX { - const val INJECT = "javax.inject:javax.inject:1" + const val INJECT = "javax.inject:javax.inject:1" + const val JAVA_ANNOTATION = "javax.annotation:javax.annotation-api:1.3.2" } object Kotlin : Version(kotlinVersion) { - val STDLIB = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version" + val STDLIB = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version" object Coroutines : Version("1.3.2") { - val ANDROID = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version" - val CORE = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" - val TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$version" + val ANDROID = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version" + val CORE = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" + val TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$version" } } object Zcash { - val ANDROID_WALLET_PLUGINS = "com.github.zcash:zcash-android-wallet-plugins:1.0.1" + const val ANDROID_WALLET_PLUGINS = "cash.z.ecc.android:zcash-android-wallet-plugins:1.0.0" + const val KOTLIN_BIP39 = "cash.z.ecc.android:kotlin-bip39:1.0.0-beta08" + object Sdk : Version("1.1.0-beta01") { + val MAINNET = "cash.z.ecc.android:sdk-mainnet:$version" + val TESTNET = "cash.z.ecc.android:sdk-testnet:$version" + } } object Misc { + const val LOTTIE = "com.airbnb.android:lottie:3.1.0" object Plugins { - val SECURE_STORAGE = "de.adorsys.android:securestoragelibrary:1.2.2" - val ANDROID_BIP39 = "cash.z.ecc.android:android-bip39:1.0.0-beta07" - val QR_SCANNER = "com.google.zxing:core:3.2.1" + const val SECURE_STORAGE = "de.adorsys.android:securestoragelibrary:1.2.2" + const val QR_SCANNER = "com.google.zxing:core:3.2.1" } } object Test { - const val JUNIT = "junit:junit:4.12" + const val JUNIT = "junit:junit:4.12" + const val MOKITO = "junit:junit:4.12" + const val COROUTINES_TEST = "junit:junit:4.12" object Android { - const val JUNIT = "androidx.test.ext:junit:1.1.1" - const val ESPRESSO = "androidx.test.espresso:espresso-core:3.2.0" + const val JUNIT = "androidx.test.ext:junit:1.1.1" + const val ESPRESSO = "androidx.test.espresso:espresso-core:3.2.0" } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3556659..c0375fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jan 07 12:00:21 EST 2020 +#Fri May 29 19:00:53 EDT 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/mnemonic/build.gradle b/mnemonic/build.gradle index b3d61be..9cb2b03 100644 --- a/mnemonic/build.gradle +++ b/mnemonic/build.gradle @@ -8,7 +8,7 @@ dependencies { // Zcash implementation Deps.Zcash.ANDROID_WALLET_PLUGINS - implementation Deps.Misc.Plugins.ANDROID_BIP39 + implementation Deps.Zcash.KOTLIN_BIP39 testImplementation Deps.Test.JUNIT } diff --git a/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt b/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt index 28dfa81..0ffbd86 100644 --- a/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt +++ b/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt @@ -1,57 +1,22 @@ package cash.z.ecc.kotlin.mnemonic import cash.z.android.plugin.MnemonicPlugin +import cash.z.ecc.android.bip39.Mnemonics import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode import cash.z.ecc.android.bip39.Mnemonics.WordCount import cash.z.ecc.android.bip39.toEntropy import cash.z.ecc.android.bip39.toSeed import java.util.* +import java.util.Locale.ENGLISH import javax.inject.Inject -class Mnemonics @Inject constructor(): MnemonicPlugin { - override fun fullWordList(languageCode: String): List { - return cash.z.ecc.android.bip39.Mnemonics.getCachedWords(Locale.ENGLISH.language) - } - - override fun nextEntropy(): ByteArray { - return WordCount.COUNT_24.toEntropy() - } - - override fun nextMnemonic(): CharArray { - return nextMnemonic(nextEntropy()) - } - - override fun nextMnemonic(entropy: ByteArray): CharArray { - return MnemonicCode(entropy).chars - } - - override fun nextMnemonicList(): List { - return nextMnemonicList(nextEntropy()) - } - - override fun nextMnemonicList(entropy: ByteArray): List { - return MnemonicCode(entropy).map { it.toCharArray() } - } - - override fun toSeed(mnemonic: CharArray): ByteArray { - return MnemonicCode(mnemonic).toSeed() - } - - override fun toWordList(mnemonic: CharArray): List { - val wordList = mutableListOf() - var cursor = 0 - repeat(mnemonic.size) { i -> - val isSpace = mnemonic[i] == ' ' - if (isSpace || i == (mnemonic.size - 1)) { - val wordSize = i - cursor + if (isSpace) 0 else 1 - wordList.add(CharArray(wordSize).apply { - repeat(wordSize) { - this[it] = mnemonic[cursor + it] - } - }) - cursor = i + 1 - } - } - return wordList - } +class Mnemonics @Inject constructor() : MnemonicPlugin { + override fun fullWordList(languageCode: String) = Mnemonics.getCachedWords(Locale.ENGLISH.language) + override fun nextEntropy(): ByteArray = WordCount.COUNT_24.toEntropy() + override fun nextMnemonic(): CharArray = MnemonicCode(WordCount.COUNT_24).chars + override fun nextMnemonic(entropy: ByteArray): CharArray = MnemonicCode(entropy).chars + override fun nextMnemonicList(): List = MnemonicCode(WordCount.COUNT_24).words + override fun nextMnemonicList(entropy: ByteArray): List = MnemonicCode(entropy).words + override fun toSeed(mnemonic: CharArray): ByteArray = MnemonicCode(mnemonic).toSeed() + override fun toWordList(mnemonic: CharArray): List = MnemonicCode(mnemonic).words } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 7d5ccd7..7878096 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,3 @@ rootProject.name='Zcash Wallet' -include ':app', ':qrecycler', ':feedback', ':mnemonic', ':lockbox', ':sdk', ':chipsinputlayout' -project(":sdk").projectDir = file("../zcash-android-wallet-sdk") +include ':app', ':qrecycler', ':feedback', ':mnemonic', ':lockbox', ':chipsinputlayout' project(":chipsinputlayout").projectDir = file("../../clones/chips-input-layout/library")