Merge pull request #286 from zcash/285-build-conventions

Refactor Gradle build setup
This commit is contained in:
Francisco Gindre 2021-09-27 15:53:18 -03:00 committed by GitHub
commit 0b3c0cf4e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1800 additions and 724 deletions

View File

@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name=":sdkLib:connectedAndroidTest" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<configuration default="false" name=":sdk-lib:connectedAndroidTest" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<module name="zcash-android-sdk.sdk-lib" />
<option name="TESTING_TYPE" value="0" />
<option name="METHOD_NAME" value="" />

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="assembleAndroidTest" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="assembleAndroidTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

60
.run/demo-app.run.xml Normal file
View File

@ -0,0 +1,60 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="demo-app" type="AndroidRunConfigurationType" factoryName="Android App" activateToolWindowBeforeRun="false">
<module name="zcash-android-sdk.demo-app" />
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
<option name="DEPLOY_AS_INSTANT" value="false" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ALL_USERS" value="false" />
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Hybrid>
<Java />
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sample Java Methods" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="dependencyUpdates" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="dependencyUpdates" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

23
.run/ktlint.run.xml Normal file
View File

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ktlint" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="ktlint" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

View File

@ -23,8 +23,6 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="true" tasks="clean publishToMavenLocal" externalProjectPath="$PROJECT_DIR$" vmOptions="" scriptParameters="" />
</method>
<method v="2" />
</configuration>
</component>

View File

@ -11,13 +11,11 @@ Publishing requires:
### Every time
1. Update the [build number](https://github.com/zcash/zcash-android-wallet-sdk/blob/master/sdk-lib/config.gradle) and the [CHANGELOG](https://github.com/zcash/zcash-android-wallet-sdk/blob/master/CHANGELOG.md)
1. Update the [build number](https://github.com/zcash/zcash-android-wallet-sdk/blob/master/gradle.properties) and the [CHANGELOG](https://github.com/zcash/zcash-android-wallet-sdk/blob/master/CHANGELOG.md)
2. Build locally
* Critical Note: Building once does not copy the *.so files and results in an artifact <1MB in size. Building twice fixes that problem and results in an artifact >5MB in size. This is probably a bug in the gradle cargo plugin that we use.
* This will install the files in your local maven repo at `~/.m2/repository/cash/z/ecc/android/`
* Build twice (first with a clean, then without):
```zsh
./gradlew clean publishToMavenLocal && ./gradlew publishToMavenLocal
./gradlew publishToMavenLocal
```
3. Publish via the following command:
```zsh
@ -32,6 +30,5 @@ Publishing requires:
Note:
Our existing artifacts can be found here and here:
https://search.maven.org/artifact/cash.z.ecc.android/zcash-android-sdk
https://repo1.maven.org/maven2/cash/z/ecc/android/
https://search.maven.org/artifact/cash.z.ecc.android/zcash-android-sdk
https://repo1.maven.org/maven2/cash/z/ecc/android/

View File

@ -219,7 +219,9 @@ This project follows [semantic versioning](https://semver.org/) with pre-release
## Examples
Examples can be found in the [Demo App](demo-app)
A primitive example to exercise the SDK exists in this repo, under [Demo App](demo-app).
There's also a more comprehensive [Sample Wallet](https://github.com/zcash/zcash-android-wallet).
[Back to contents](#contents)
@ -229,3 +231,6 @@ Publishing instructions for maintainers of this repository can be found in [PUBL
[Back to contents](#contents)
# Known Issues
1. During builds, a warning will be printed that says "Unable to detect AGP versions for included builds. All projects in the build should use the same AGP version." This can be safely ignored. The version under build-conventions is the same as the version used elsewhere in the application.

View File

@ -0,0 +1,20 @@
import org.jetbrains.kotlin.konan.properties.loadProperties
plugins {
`kotlin-dsl`
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin")
implementation("com.android.tools.build:gradle:${getAndroidGradlePluginVersion()}")
}
fun getAndroidGradlePluginVersion(): String {
// A slightly gross way to use the root gradle.properties as the single source of truth for version numbers
val properties = run {
val rootPropertiesFile = File(project.projectDir.parentFile, "gradle.properties")
loadProperties(rootPropertiesFile.path)
}
return properties.getProperty("ANDROID_GRADLE_PLUGIN_VERSION")
}

View File

@ -0,0 +1,15 @@
pluginManagement {
repositories {
gradlePluginPortal()
}
}
@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
rootProject.name = "build-conventions"

View File

@ -0,0 +1,85 @@
pluginManager.withPlugin("com.android.application") {
project.the<com.android.build.gradle.AppExtension>().apply {
configureBaseExtension()
defaultConfig {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
// en_XA and ar_XB are pseudolocales for debugging.
// The rest of the locales provides an explicit list of the languages to keep in the
// final app. Doing this will strip out additional locales from libraries like
// Google Play Services and Firebase, which add unnecessary bloat.
resourceConfigurations.addAll(listOf("en", "en-rUS", "en-rGB", "en-rAU", "en_XA", "ar_XB"))
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
}
}
}
pluginManager.withPlugin("com.android.library") {
project.the<com.android.build.gradle.LibraryExtension>().apply {
configureBaseExtension()
defaultConfig {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
// The last two are for support of pseudolocales in debug builds.
// If we add other localizations, they should be included in this list.
// By explicitly setting supported locales, we strip out unused localizations from third party
// libraries (e.g. play services)
resourceConfigurations.addAll(listOf("en", "en-rUS", "en-rGB", "en-rAU", "en_XA", "ar_XB"))
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("proguard-consumer.txt")
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
testInstrumentationRunnerArguments["clearPackageData"] = "true"
}
}
testCoverage {
jacocoVersion = project.property("JACOCO_VERSION").toString()
}
}
}
fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
compileSdkVersion(project.property("ANDROID_COMPILE_SDK_VERSION").toString().toInt())
ndkVersion = project.property("ANDROID_NDK_VERSION").toString()
compileOptions {
val javaVersion = JavaVersion.toVersion(project.property("ANDROID_JVM_TARGET").toString())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}
buildTypes {
getByName("debug").apply {
isTestCoverageEnabled = project.property("IS_COVERAGE_ENABLED").toString().toBoolean()
}
}
signingConfigs {
val debugKeystorePath = project.property("ZCASH_DEBUG_KEYSTORE_PATH").toString()
val isExplicitDebugSigningEnabled = !debugKeystorePath.isNullOrBlank()
if (isExplicitDebugSigningEnabled) {
// If this block doesn't execute, the output will still be signed with the default keystore
getByName("debug").apply {
storeFile = File(debugKeystorePath)
}
}
}
testOptions {
animationsDisabled = true
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}
}

View File

@ -0,0 +1,34 @@
plugins {
id("java")
}
val ktlint by configurations.creating
dependencies {
ktlint("com.pinterest:ktlint:${project.property("KTLINT_VERSION")}")
}
tasks {
val editorConfigFile = rootProject.file(".editorconfig")
val ktlintArgs = listOf("**/src/**/*.kt", "!**/build/**.kt", "--editorconfig=$editorConfigFile")
register("ktlint", org.gradle.api.tasks.JavaExec::class) {
description = "Check code style with ktlint"
classpath = ktlint
mainClass.set("com.pinterest.ktlint.Main")
args = ktlintArgs
}
register("ktlintFormat", org.gradle.api.tasks.JavaExec::class) {
description = "Apply code style formatting with ktlint"
classpath = ktlint
mainClass.set("com.pinterest.ktlint.Main")
args = listOf("-F") + ktlintArgs
}
}
java {
val javaVersion = JavaVersion.toVersion(project.property("ANDROID_JVM_TARGET").toString())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}

View File

@ -1,26 +0,0 @@
buildscript {
repositories {
google()
mavenCentral()
maven {
url "https://jitpack.io"
}
gradlePluginPortal()
}
dependencies {
//noinspection GradlePluginVersion
classpath "com.android.tools.build:gradle:_"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:_"
classpath "org.jetbrains.kotlin:kotlin-allopen:_"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:_"
classpath "com.google.protobuf:protobuf-gradle-plugin:_"
classpath 'org.mozilla.rust-android-gradle:plugin:0.9.0'
classpath "org.owasp:dependency-check-gradle:_"
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.17.0'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:_"
}
}
apply plugin: "org.jetbrains.dokka"
apply plugin: "org.owasp.dependencycheck"

58
build.gradle.kts Normal file
View File

@ -0,0 +1,58 @@
buildscript {
repositories {
google()
gradlePluginPortal()
}
dependencies {
classpath(libs.gradle.plugin.android)
classpath(libs.gradle.plugin.rust)
classpath(libs.gradle.plugin.publish)
classpath(libs.gradle.plugin.navigation)
}
}
plugins {
id("org.jetbrains.dokka")
id("org.owasp.dependencycheck")
id("zcash.ktlint-conventions")
id("io.gitlab.arturbosch.detekt")
id("com.github.ben-manes.versions")
}
tasks {
register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) {
parallel = true
setSource(files(projectDir))
include("**/*.kt")
include("**/*.kts")
exclude("**/resources/**")
exclude("**/build/**")
exclude("**/commonTest/**")
exclude("**/jvmTest/**")
exclude("**/androidTest/**")
config.setFrom(files("${rootProject.projectDir}/tools/detekt.yml"))
buildUponDefaultConfig = true
}
withType<com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask> {
gradleReleaseChannel = "current"
resolutionStrategy {
componentSelection {
all {
if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
reject("Unstable")
}
}
}
}
}
}
val unstableKeywords = listOf("alpha", "beta", "rc", "m", "ea", "build")
fun isNonStable(version: String): Boolean {
val versionLowerCase = version.toLowerCase()
return unstableKeywords.any { versionLowerCase.contains(it) }
}

View File

@ -1,77 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs'
android {
ndkVersion project.property("ndkVersion")
compileSdkVersion Integer.parseInt(project.property("compileSdkVersion"))
defaultConfig {
applicationId "cash.z.ecc.android.sdk.demoapp"
minSdkVersion 21 // Different from the SDK min
targetSdkVersion Integer.parseInt(project.property("targetSdkVersion"))
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
viewBinding true
}
flavorDimensions 'network'
productFlavors {
// would rather name them "testnet" and "mainnet" but product flavor names cannot start with the word "test"
zcashtestnet {
dimension 'network'
applicationId 'cash.z.ecc.android.sdk.demoapp.testnet'
matchingFallbacks = ['zcashtestnet', 'debug']
}
zcashmainnet {
dimension 'network'
applicationId 'cash.z.ecc.android.sdk.demoapp.mainnet'
matchingFallbacks = ['zcashmainnet', 'release']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
kotlinOptions {
jvmTarget = "1.8"
}
lintOptions {
baseline file("lint-baseline.xml")
}
}
dependencies {
// SDK
implementation(projects.sdkLib)
//implementation('cash.z.ecc.android:zcash-android-sdk:1.3.0-beta17')
// sample mnemonic plugin
implementation 'com.github.zcash:zcash-android-wallet-plugins:1.0.1'
implementation 'cash.z.ecc.android:kotlin-bip39:1.0.2'
// Android
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation "com.google.android.material:material:1.3.0-alpha03"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation "io.grpc:grpc-android:1.39.0"
implementation "io.grpc:grpc-okhttp:1.39.0"
implementation "io.grpc:grpc-protobuf-lite:1.39.0"
implementation "io.grpc:grpc-stub:1.39.0"
}

76
demo-app/build.gradle.kts Normal file
View File

@ -0,0 +1,76 @@
plugins {
id("com.android.application")
id("zcash.android-build-conventions")
id("kotlin-android")
id("kotlin-parcelize")
id("androidx.navigation.safeargs")
}
android {
defaultConfig {
applicationId = "cash.z.ecc.android.sdk.demoapp"
minSdk = 21 // Different from the SDK min
versionCode = 1
versionName = "1.0"
}
buildFeatures {
viewBinding = true
}
flavorDimensions.add("network")
productFlavors {
// would rather name them "testnet" and "mainnet" but product flavor names cannot start with the word "test"
create("zcashtestnet") {
dimension = "network"
applicationId = "cash.z.ecc.android.sdk.demoapp.testnet"
matchingFallbacks.addAll(listOf("zcashtestnet", "debug"))
}
create("zcashmainnet") {
dimension = "network"
applicationId = "cash.z.ecc.android.sdk.demoapp.mainnet"
matchingFallbacks.addAll(listOf("zcashmainnet", "release"))
}
}
buildTypes {
getByName("release").apply {
isMinifyEnabled = project.property("IS_MINIFY_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
File("proguard-project.txt")
)
)
}
}
kotlinOptions {
jvmTarget = libs.versions.java.get()
allWarningsAsErrors = project.property("IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
}
lint {
baseline(File("lint-baseline.xml"))
}
}
dependencies {
// SDK
implementation(projects.sdkLib)
// sample mnemonic plugin
implementation(libs.zcashwalletplgn)
implementation(libs.bip39)
// Android
implementation(libs.androidx.core)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.navigation.ui)
implementation(libs.material)
androidTestImplementation(libs.bundles.androidx.test)
implementation(libs.bundles.grpc)
}

View File

@ -1,6 +1,6 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@ -1,18 +1,17 @@
package cash.z.ecc.android.sdk.sample.demoapp
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.entity.isFailure
import cash.z.ecc.android.sdk.transaction.*
import cash.z.ecc.android.sdk.ext.*
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.jni.RustBackend
import cash.z.ecc.android.sdk.service.LightWalletGrpcService
import kotlinx.coroutines.cancel
import cash.z.ecc.android.sdk.transaction.PagedTransactionRepository
import cash.z.ecc.android.sdk.transaction.WalletTransactionEncoder
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Test
@ -45,8 +44,7 @@ class SampleCodeTest {
// log(entropy.asSeedPhrase())
}
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// Derive Extended Spending Key
@Test fun deriveSpendingKey() {
val spendingKeys = RustBackend().deriveSpendingKeys(seed)
@ -54,7 +52,7 @@ class SampleCodeTest {
log("Spending Key: ${spendingKeys?.get(0)}")
}
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// Get Address
@Test fun getAddress() = runBlocking {
val address = synchronizer.getAddress()
@ -62,10 +60,9 @@ class SampleCodeTest {
log("Address: $address")
}
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// Derive address from Extended Full Viewing Key
@Test fun getAddressFromViewingKey() {
}
// ///////////////////////////////////////////////////
@ -91,13 +88,11 @@ class SampleCodeTest {
// ///////////////////////////////////////////////////
// Query account outgoing transactions
@Test fun queryOutgoingTransactions() {
}
// ///////////////////////////////////////////////////
// Query account incoming transactions
@Test fun queryIncomingTransactions() {
}
// ///////////////////////////////////////////////////
@ -131,10 +126,9 @@ class SampleCodeTest {
}
}
///////////////////////////////////////////////////////
// /////////////////////////////////////////////////////
// Utility Functions
//////////////////////////////////////////////////////
// ////////////////////////////////////////////////////
companion object {
private val seed = "Insert seed for testing".toByteArray()

View File

@ -12,8 +12,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.viewbinding.ViewBinding
import cash.z.ecc.android.sdk.demoapp.util.mainActivity
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
import cash.z.ecc.android.sdk.ext.Twig
import com.google.android.material.snackbar.Snackbar
abstract class BaseDemoFragment<T : ViewBinding> : Fragment() {
@ -24,11 +22,11 @@ abstract class BaseDemoFragment<T : ViewBinding> : Fragment() {
* synchronizer because it wraps the service.
*/
val lightwalletService get() = mainActivity()?.lightwalletService
// contains view information provided by the user
val sharedViewModel: SharedViewModel by activityViewModels()
lateinit var binding: T
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,

View File

@ -24,7 +24,9 @@ import cash.z.ecc.android.sdk.type.ZcashNetwork
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView
class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedListener,
class MainActivity :
AppCompatActivity(),
ClipboardManager.OnPrimaryClipChangedListener,
DrawerLayout.DrawerListener {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var clipboard: ClipboardManager
@ -38,7 +40,7 @@ class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedL
* automatically sync with the server.
*/
var lightwalletService: LightWalletService? = null
private set
private set
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -62,7 +64,8 @@ class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedL
R.id.nav_home, R.id.nav_address, R.id.nav_balance, R.id.nav_block, R.id.nav_private_key,
R.id.nav_latest_height, R.id.nav_block_range,
R.id.nav_transactions, R.id.nav_utxos, R.id.nav_send
), drawerLayout
),
drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
@ -97,7 +100,6 @@ class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedL
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
//
// Private functions
//
@ -113,7 +115,6 @@ class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedL
fabListener?.onActionButtonClicked()
}
//
// Helpers
//
@ -143,7 +144,6 @@ class MainActivity : AppCompatActivity(), ClipboardManager.OnPrimaryClipChangedL
getSystemService<InputMethodManager>()?.hideSoftInputFromWindow(windowToken, 0)
}
/* DrawerListener implementation */
override fun onDrawerStateChanged(newState: Int) {

View File

@ -29,6 +29,6 @@ class SharedViewModel : ViewModel() {
return try {
Mnemonics.MnemonicCode(phrase).validate()
true
} catch (t: Throwable){ false }
} catch (t: Throwable) { false }
}
}

View File

@ -6,7 +6,6 @@ import android.os.Handler
import android.os.Looper
import android.os.StrictMode
object StrictModeHelper {
fun enableStrictMode() {

View File

@ -60,7 +60,6 @@ class GetAddressFragment : BaseDemoFragment<FragmentGetAddressBinding>() {
displayAddress()
}
//
// Base Fragment overrides
//
@ -74,5 +73,4 @@ class GetAddressFragment : BaseDemoFragment<FragmentGetAddressBinding>() {
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetAddressBinding =
FragmentGetAddressBinding.inflate(layoutInflater)
}

View File

@ -2,14 +2,12 @@ package cash.z.ecc.android.sdk.demoapp.demos.getbalance
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.lifecycleScope
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentGetBalanceBinding
import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
@ -48,12 +46,12 @@ class GetBalanceFragment : BaseDemoFragment<FragmentGetBalanceBinding>() {
val viewingKey = DerivationTool.deriveUnifiedViewingKeys(seed, ZcashNetwork.fromResources(requireApplicationContext())).first()
// using the ViewingKey to initialize
Initializer(requireApplicationContext()) {
it.setNetwork(ZcashNetwork.fromResources(requireApplicationContext()))
it.importWallet(viewingKey, network = ZcashNetwork.fromResources(requireApplicationContext()))
}.let { initializer ->
synchronizer = Synchronizer(initializer)
}
Initializer(requireApplicationContext()) {
it.setNetwork(ZcashNetwork.fromResources(requireApplicationContext()))
it.importWallet(viewingKey, network = ZcashNetwork.fromResources(requireApplicationContext()))
}.let { initializer ->
synchronizer = Synchronizer(initializer)
}
}
override fun onResume() {
@ -71,14 +69,12 @@ class GetBalanceFragment : BaseDemoFragment<FragmentGetBalanceBinding>() {
}
private fun onBalance(balance: WalletBalance) {
binding.textBalance.text = """
binding.textBalance.text = """
Available balance: ${balance.availableZatoshi.convertZatoshiToZecString(12)}
Total balance: ${balance.totalZatoshi.convertZatoshiToZecString(12)}
""".trimIndent()
""".trimIndent()
}
private fun onStatus(status: Synchronizer.Status) {
binding.textStatus.text = "Status: $status"
if (WalletBalance().none()) {
@ -97,9 +93,10 @@ class GetBalanceFragment : BaseDemoFragment<FragmentGetBalanceBinding>() {
/**
* Extension function which checks if the balance has been updated or its -1
*/
private fun WalletBalance.none(): Boolean{
if(synchronizer.saplingBalances.value.totalZatoshi == -1L
&& synchronizer.saplingBalances.value.availableZatoshi == -1L) return true
private fun WalletBalance.none(): Boolean {
if (synchronizer.saplingBalances.value.totalZatoshi == -1L &&
synchronizer.saplingBalances.value.availableZatoshi == -1L
) return true
return false
}

View File

@ -52,7 +52,6 @@ class GetBlockFragment : BaseDemoFragment<FragmentGetBlockBinding>() {
onApply()
}
//
// Android Lifecycle overrides
//
@ -68,7 +67,6 @@ class GetBlockFragment : BaseDemoFragment<FragmentGetBlockBinding>() {
}
}
//
// Base Fragment overrides
//

View File

@ -28,41 +28,43 @@ class GetBlockRangeFragment : BaseDemoFragment<FragmentGetBlockRangeBinding>() {
// Note: This is a demo so we won't worry about iterating efficiently over these blocks
binding.textInfo.text = Html.fromHtml(blocks?.run {
val count = size
val emptyCount = count { it.vtxCount == 0 }
val maxTxs = maxByOrNull { it.vtxCount }
val maxIns = maxByOrNull { block ->
block.vtxList.maxOfOrNull { it.spendsCount } ?: -1
}
val maxInTx = maxIns?.vtxList?.maxByOrNull { it.spendsCount }
val maxOuts = maxByOrNull { block ->
block.vtxList.maxOfOrNull { it.outputsCount } ?: -1
}
val maxOutTx = maxOuts?.vtxList?.maxByOrNull { it.outputsCount }
val txCount = sumBy { it.vtxCount }
val outCount = sumBy { block -> block.vtxList.sumBy { it.outputsCount } }
val inCount = sumBy { block -> block.vtxList.sumBy { it.spendsCount } }
binding.textInfo.text = Html.fromHtml(
blocks?.run {
val count = size
val emptyCount = count { it.vtxCount == 0 }
val maxTxs = maxByOrNull { it.vtxCount }
val maxIns = maxByOrNull { block ->
block.vtxList.maxOfOrNull { it.spendsCount } ?: -1
}
val maxInTx = maxIns?.vtxList?.maxByOrNull { it.spendsCount }
val maxOuts = maxByOrNull { block ->
block.vtxList.maxOfOrNull { it.outputsCount } ?: -1
}
val maxOutTx = maxOuts?.vtxList?.maxByOrNull { it.outputsCount }
val txCount = sumBy { it.vtxCount }
val outCount = sumBy { block -> block.vtxList.sumBy { it.outputsCount } }
val inCount = sumBy { block -> block.vtxList.sumBy { it.spendsCount } }
val processTime = System.currentTimeMillis() - start - fetchDelta
"""
val processTime = System.currentTimeMillis() - start - fetchDelta
"""
<b>total blocks:</b> ${count.withCommas()}
<br/><b>fetch time:</b> ${if (fetchDelta > 1000) "%.2f sec".format(fetchDelta/1000.0) else "%d ms".format(fetchDelta)}
<br/><b>process time:</b> ${if (processTime > 1000) "%.2f sec".format(processTime/1000.0) else "%d ms".format(processTime)}
<br/><b>fetch time:</b> ${if (fetchDelta > 1000) "%.2f sec".format(fetchDelta / 1000.0) else "%d ms".format(fetchDelta)}
<br/><b>process time:</b> ${if (processTime > 1000) "%.2f sec".format(processTime / 1000.0) else "%d ms".format(processTime)}
<br/><b>block time range:</b> ${first().time.toRelativeTime(requireApplicationContext())}<br/>&nbsp;&nbsp to ${last().time.toRelativeTime(requireApplicationContext())}
<br/><b>total empty blocks:</b> ${emptyCount.withCommas()}
<br/><b>total TXs:</b> ${txCount.withCommas()}
<br/><b>total outputs:</b> ${outCount.withCommas()}
<br/><b>total inputs:</b> ${inCount.withCommas()}
<br/><b>avg TXs/block:</b> ${"%.1f".format(txCount/count.toDouble())}
<br/><b>avg TXs (excluding empty blocks):</b> ${"%.1f".format(txCount.toDouble()/(count - emptyCount))}
<br/><b>avg OUTs [per block / per TX]:</b> ${"%.1f / %.1f".format(outCount.toDouble()/(count - emptyCount), outCount.toDouble()/txCount)}
<br/><b>avg INs [per block / per TX]:</b> ${"%.1f / %.1f".format(inCount.toDouble()/(count - emptyCount), inCount.toDouble()/txCount)}
<br/><b>most shielded TXs:</b> ${if (maxTxs==null) "none" else "${maxTxs.vtxCount} in block ${maxTxs.height.withCommas()}"}
<br/><b>most shielded INs:</b> ${if (maxInTx==null) "none" else "${maxInTx.spendsCount} in block ${maxIns?.height.withCommas()} at tx index ${maxInTx.index}"}
<br/><b>most shielded OUTs:</b> ${if (maxOutTx==null) "none" else "${maxOutTx?.outputsCount} in block ${maxOuts?.height.withCommas()} at tx index ${maxOutTx?.index}"}
""".trimIndent()
} ?: "No blocks found in that range.")
<br/><b>avg TXs/block:</b> ${"%.1f".format(txCount / count.toDouble())}
<br/><b>avg TXs (excluding empty blocks):</b> ${"%.1f".format(txCount.toDouble() / (count - emptyCount))}
<br/><b>avg OUTs [per block / per TX]:</b> ${"%.1f / %.1f".format(outCount.toDouble() / (count - emptyCount), outCount.toDouble() / txCount)}
<br/><b>avg INs [per block / per TX]:</b> ${"%.1f / %.1f".format(inCount.toDouble() / (count - emptyCount), inCount.toDouble() / txCount)}
<br/><b>most shielded TXs:</b> ${if (maxTxs == null) "none" else "${maxTxs.vtxCount} in block ${maxTxs.height.withCommas()}"}
<br/><b>most shielded INs:</b> ${if (maxInTx == null) "none" else "${maxInTx.spendsCount} in block ${maxIns?.height.withCommas()} at tx index ${maxInTx.index}"}
<br/><b>most shielded OUTs:</b> ${if (maxOutTx == null) "none" else "${maxOutTx?.outputsCount} in block ${maxOuts?.height.withCommas()} at tx index ${maxOutTx?.index}"}
""".trimIndent()
} ?: "No blocks found in that range."
)
}
private fun onApply(_unused: View) {
@ -93,7 +95,6 @@ class GetBlockRangeFragment : BaseDemoFragment<FragmentGetBlockRangeBinding>() {
binding.textInfo.text = "Error: $message"
}
//
// Android Lifecycle overrides
//
@ -103,7 +104,6 @@ class GetBlockRangeFragment : BaseDemoFragment<FragmentGetBlockRangeBinding>() {
binding.buttonApply.setOnClickListener(::onApply)
}
//
// Base Fragment overrides
//
@ -114,5 +114,4 @@ class GetBlockRangeFragment : BaseDemoFragment<FragmentGetBlockRangeBinding>() {
override fun onActionButtonClicked() {
super.onActionButtonClicked()
}
}

View File

@ -18,7 +18,6 @@ class GetLatestHeightFragment : BaseDemoFragment<FragmentGetLatestHeightBinding>
binding.textInfo.text = lightwalletService?.getLatestBlockHeight().toString()
}
//
// Android Lifecycle overrides
//
@ -28,7 +27,6 @@ class GetLatestHeightFragment : BaseDemoFragment<FragmentGetLatestHeightBinding>
displayLatestHeight()
}
//
// Base Fragment overrides
//

View File

@ -37,7 +37,7 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
private fun displayKeys() {
// derive the keys from the seed:
// demonstrate deriving spending keys for five accounts but only take the first one
val spendingKey = DerivationTool.deriveSpendingKeys(seed, ZcashNetwork.fromResources(requireApplicationContext()),5).first()
val spendingKey = DerivationTool.deriveSpendingKeys(seed, ZcashNetwork.fromResources(requireApplicationContext()), 5).first()
// derive the key that allows you to view but not spend transactions
val viewingKey = DerivationTool.deriveViewingKey(spendingKey, ZcashNetwork.fromResources(requireApplicationContext()))
@ -46,7 +46,6 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
binding.textInfo.setText("Spending Key:\n$spendingKey\n\nViewing Key:\n$viewingKey")
}
//
// Android Lifecycle overrides
//
@ -61,7 +60,6 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
displayKeys()
}
//
// Base Fragment overrides
//
@ -75,5 +73,4 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetPrivateKeyBinding =
FragmentGetPrivateKeyBinding.inflate(layoutInflater)
}

View File

@ -5,17 +5,11 @@ import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
import cash.z.ecc.android.sdk.demoapp.SharedViewModel
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentHomeBinding
import cash.z.ecc.android.sdk.demoapp.util.mainActivity
import cash.z.ecc.android.sdk.ext.twig
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@ -121,4 +115,3 @@ class HomeFragment : BaseDemoFragment<FragmentHomeBinding>() {
}
}
}

View File

@ -1,9 +1,5 @@
package cash.z.ecc.android.sdk.demoapp.demos.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class HomeViewModel : ViewModel() {
}
class HomeViewModel : ViewModel()

View File

@ -8,11 +8,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.SdkSynchronizer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentListTransactionsBinding
import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
@ -37,7 +35,6 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
private var status: Synchronizer.Status? = null
private val isSynced get() = status == Synchronizer.Status.SYNCED
/**
* Initialize the required values that would normally live outside the demo but are repeated
* here for completeness so that each demo file can serve as a standalone example.
@ -73,7 +70,6 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
synchronizer.clearedTransactions.collectWith(lifecycleScope, ::onTransactionsUpdated)
}
//
// Change listeners
//
@ -107,7 +103,7 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
visibility = View.VISIBLE
text =
"No transactions found. Try to either change the seed words " +
"or send funds to this address (tap the FAB to copy it):\n\n $address"
"or send funds to this address (tap the FAB to copy it):\n\n $address"
} else {
visibility = View.INVISIBLE
text = ""
@ -116,7 +112,6 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
}
}
//
// Android Lifecycle overrides
//
@ -138,7 +133,6 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
monitorChanges()
}
//
// Base Fragment overrides
//
@ -149,5 +143,4 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentListTransactionsBinding =
FragmentListTransactionsBinding.inflate(layoutInflater)
}

View File

@ -4,8 +4,8 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
import cash.z.ecc.android.sdk.demoapp.R
/**
* Simple adapter implementation that knows how to bind a recyclerview to ClearedTransactions.
@ -36,5 +36,4 @@ class TransactionAdapter<T : ConfirmedTransaction> :
holder: TransactionViewHolder<T>,
position: Int
) = holder.bindTo(getItem(position))
}

View File

@ -1,19 +1,15 @@
package cash.z.ecc.android.sdk.demoapp.demos.listtransactions
import android.content.res.ColorStateList
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import java.text.SimpleDateFormat
import java.util.*
import java.util.Locale
/**
* Simple view holder for displaying confirmed transactions in the recyclerview.

View File

@ -12,7 +12,6 @@ import cash.z.ecc.android.sdk.SdkSynchronizer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
import cash.z.ecc.android.sdk.demoapp.DemoConstants
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentListUtxosBinding
@ -28,7 +27,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* ===============================================================================================
* NOTE: this is still a WIP because t-addrs are not officially supported by the SDK yet
@ -159,7 +157,6 @@ class ListUtxosFragment : BaseDemoFragment<FragmentListUtxosBinding>() {
binding.inputAddress.setText(DerivationTool.deriveTransparentAddress(seed, ZcashNetwork.fromResources(requireApplicationContext())))
}
var initialCount: Int = 0
var finalCount: Int = 0
fun resetInBackground() {
@ -193,12 +190,11 @@ class ListUtxosFragment : BaseDemoFragment<FragmentListUtxosBinding>() {
adapter = UtxoAdapter()
binding.recyclerTransactions.adapter = adapter
// lifecycleScope.launch {
//// address = synchronizer.getAddress()
// // address = synchronizer.getAddress()
// synchronizer.receivedTransactions.onEach {
// onTransactionsUpdated(it)
// }.launchIn(this)
// }
}
private fun startSynchronizer() {

View File

@ -36,5 +36,4 @@ class UtxoAdapter<T : ConfirmedTransaction> :
holder: UtxoViewHolder<T>,
position: Int
) = holder.bindTo(getItem(position))
}

View File

@ -3,11 +3,11 @@ package cash.z.ecc.android.sdk.demoapp.demos.listutxos
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import java.text.SimpleDateFormat
import java.util.*
import java.util.Locale
/**
* Simple view holder for displaying confirmed transactions in the recyclerview.

View File

@ -10,14 +10,25 @@ import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.Initializer
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.db.entity.*
import cash.z.ecc.android.sdk.db.entity.PendingTransaction
import cash.z.ecc.android.sdk.db.entity.isCreated
import cash.z.ecc.android.sdk.db.entity.isCreating
import cash.z.ecc.android.sdk.db.entity.isFailedEncoding
import cash.z.ecc.android.sdk.db.entity.isFailedSubmit
import cash.z.ecc.android.sdk.db.entity.isMined
import cash.z.ecc.android.sdk.db.entity.isSubmitSuccess
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
import cash.z.ecc.android.sdk.demoapp.DemoConstants
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentSendBinding
import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
import cash.z.ecc.android.sdk.demoapp.util.fromResources
import cash.z.ecc.android.sdk.demoapp.util.mainActivity
import cash.z.ecc.android.sdk.ext.*
import cash.z.ecc.android.sdk.ext.Twig
import cash.z.ecc.android.sdk.ext.collectWith
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import cash.z.ecc.android.sdk.ext.convertZecToZatoshi
import cash.z.ecc.android.sdk.ext.toZecString
import cash.z.ecc.android.sdk.ext.twig
import cash.z.ecc.android.sdk.tool.DerivationTool
import cash.z.ecc.android.sdk.type.WalletBalance
import cash.z.ecc.android.sdk.type.ZcashNetwork
@ -40,7 +51,6 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
// but since this is a demo, we'll derive it on the fly
private lateinit var spendingKey: String
/**
* Initialize the required values that would normally live outside the demo but are repeated
* here for completeness so that each demo file can serve as a standalone example.
@ -83,7 +93,6 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
onUpdateSendButton()
}
//
// Private functions
//
@ -105,7 +114,6 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
synchronizer.saplingBalances.collectWith(lifecycleScope, ::onBalance)
}
//
// Change listeners
//
@ -198,7 +206,6 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
binding.textInfo.text = "Active Transaction:"
}
//
// Android Lifecycle overrides
//
@ -226,5 +233,4 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentSendBinding =
FragmentSendBinding.inflate(layoutInflater)
}

View File

@ -3,7 +3,6 @@ package cash.z.ecc.android.sdk.demoapp.util
import android.content.Context
import android.text.format.DateUtils
import androidx.fragment.app.Fragment
import cash.z.ecc.android.sdk.demoapp.App
import cash.z.ecc.android.sdk.demoapp.MainActivity
import cash.z.wallet.sdk.rpc.CompactFormats
@ -11,10 +10,8 @@ import cash.z.wallet.sdk.rpc.CompactFormats
* Lazy extensions to make demo life easier.
*/
fun Fragment.mainActivity() = context as? MainActivity
/**
* Add locale-specific commas to a number, if it exists.
*/
@ -34,7 +31,6 @@ fun Int?.toRelativeTime(context: Context) =
).toString()
} ?: "Unknown"
fun List<CompactFormats.CompactTx>?.toHtml() =
this.takeUnless { it.isNullOrEmpty() }?.let { txs ->
buildString {
@ -42,4 +38,3 @@ fun List<CompactFormats.CompactTx>?.toHtml() =
txs.forEach { append("<br/><b>&nbsp;&nbsp;tx${it.index}:</b> ${it.spendsCount} / ${it.outputsCount}") }
}
} ?: ""

View File

@ -4,5 +4,8 @@ import android.content.Context
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.type.ZcashNetwork
fun ZcashNetwork.Companion.fromResources(context: Context) = ZcashNetwork.valueOf(context.getString(
R.string.network_name))
fun ZcashNetwork.Companion.fromResources(context: Context) = ZcashNetwork.valueOf(
context.getString(
R.string.network_name
)
)

View File

@ -1,19 +1,17 @@
package cash.z.ecc.android.sdk.demoapp.util
import android.content.Context
import cash.z.ecc.android.sdk.demoapp.App
@Deprecated(
message = "Do not use this! It is insecure and only intended for demo purposes to " +
"show how to bridge to an existing key storage mechanism. Instead, use the Android " +
"Keystore system or a 3rd party library that leverages it."
"show how to bridge to an existing key storage mechanism. Instead, use the Android " +
"Keystore system or a 3rd party library that leverages it."
)
class SampleStorage(context: Context) {
private val prefs =
context.applicationContext.getSharedPreferences("ExtremelyInsecureStorage", Context.MODE_PRIVATE)
fun saveSensitiveString(key: String, value: String) {
prefs.edit().putString(key, value).apply()
}
@ -54,8 +52,8 @@ class SampleStorageBridge(context: Context) {
return this
}
val seed: ByteArray get() = delegate.loadSensitiveBytes(KEY_SEED)!!
val key get() = delegate.loadSensitiveString(KEY_PK)!!
val seed: ByteArray get() = delegate.loadSensitiveBytes(KEY_SEED)!!
val key get() = delegate.loadSensitiveString(KEY_PK)!!
companion object {
private const val KEY_SEED = "cash.z.ecc.android.sdk.demoapp.SEED"

View File

@ -6,7 +6,7 @@ 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
/**
* A sample implementation of a plugin for handling Mnemonic phrases. Any library can easily be

View File

@ -11,4 +11,4 @@ object DemoConstants {
// corresponds to seed: urban kind wise collect social marble riot primary craft lucky head cause syrup odor artist decorate rhythm phone style benefit portion bus truck top
val toAddress: String =
"zs1lcdmue7rewgvzh3jd09sfvwq3sumu6hkhpk53q94kcneuffjkdg9e3tyxrugkmpza5c3c5e6eqh"
}
}

View File

@ -1,31 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
# Speed up builds. Keep these flags here for quick debugging of issues.
org.gradle.vfs.watch=true
org.gradle.configureondemand=false
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2g
kapt.include.compile.classpath=false
kapt.incremental.apt=true
kapt.use.worker.api=true
android.useAndroidX=true
# support libraries have long been changed to AndroidX I think we can stop leaning on jetifier now!
#android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.builder.sdkDownload=true
# Publishing Constants
# Publishing
LIBRARY_VERSION=1.3.0-beta18
POM_NAME=Zcash Android Wallet SDK
POM_ARTIFACT_ID=zcash-android-sdk
POM_DESCRIPTION=This lightweight SDK connects Android to Zcash. It welds together Rust and Kotlin in a minimal way, allowing third-party Android apps to send and receive shielded transactions easily, securely and privately.
POM_INCEPTION_YEAR=2018
POM_URL=https://github.com/zcash/zcash-android-wallet-sdk/
@ -39,9 +29,75 @@ POM_DEVELOPER_ID=gmale
POM_DEVELOPER_NAME=Kevin Gorham
POM_DEVELOPER_URL=https://github.com/gmale/
# Kotlin compiler warnings can be considered errors, failing the build.
# Currently set to false, because this project has a lot of warnings to fix first.
IS_TREAT_WARNINGS_AS_ERRORS=false
# Optionally configure code coverage, as historically Jacoco has at times been buggy with respect to new Kotlin versions
IS_COVERAGE_ENABLED=false
# Optionally configure test orchestrator.
# It is disabled by default, because it causes tests to take about 2x longer to run.
IS_USE_TEST_ORCHESTRATOR=false
# Optionally configure minification
IS_MINIFY_ENABLED=false
# Set keystore details to enable build signing. Typically these
# are overridden via ~/.gradle/gradle.properties to allow secure injection.
# Debug keystore is useful if using Google Maps or Firebase, which require API keys to be linked
# to a signing key. Without a debug keystore, the default Android debug keystore will be used.
ZCASH_DEBUG_KEYSTORE_PATH=
# Versions
ANDROID_MIN_SDK_VERSION=16
ANDROID_TARGET_SDK_VERSION=31
ANDROID_COMPILE_SDK_VERSION=31
# Note: When updating the NDK version here, be sure to update the version on the CI server as well
ndkVersion=21.1.6352462
minSdkVersion=16
targetSdkVersion=31
compileSdkVersion=31
ANDROID_NDK_VERSION=21.1.6352462
ANDROID_GRADLE_PLUGIN_VERSION=7.0.2
DETEKT_VERSION=1.18.1
DOKKA_VERSION=1.4.30
GRADLE_VERSIONS_PLUGIN_VERSION=0.38.0
KTLINT_VERSION=0.42.1
MAVEN_PUBLISH_GRADLE_PLUGIN=0.17.0
OWASP_DEPENDENCY_CHECK_VERSION=6.3.1
PROTOBUF_GRADLE_PLUGIN_VERSION=0.8.17
RUST_GRADLE_PLUGIN_VERSION=0.9.0
ANDROIDX_ANNOTATION_VERSION=1.2.0
ANDROIDX_APPCOMPAT_VERSION=1.3.1
ANDROIDX_CONSTRAINT_LAYOUT_VERSION=2.0.4
ANDROIDX_CORE_VERSION=1.3.2
ANDROIDX_ESPRESSO_VERSION=3.4.0
ANDROIDX_LIFECYCLE_VERSION=2.3.1
ANDROIDX_MULTIDEX_VERSION=2.0.1
ANDROIDX_NAVIGATION_VERSION=2.3.5
ANDROIDX_PAGING_VERSION=2.1.2
ANDROIDX_ROOM_VERSION=2.3.0
ANDROIDX_TEST_JUNIT_VERSION=1.1.3
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.1.0-alpha1
ANDROIDX_TEST_VERSION=1.3.0
ANDROIDX_UI_AUTOMATOR_VERSION=2.2.0-alpha1
BIP39_VERSION=1.0.2
COROUTINES_OKHTTP=1.0
GOOGLE_MATERIAL_VERSION=1.3.0-alpha03
GRPC_VERSION=1.38.1
GSON_VERSION=2.8.6
GUAVA_VERSION=30.0-android
JACOCO_VERSION=0.8.7
JAVAX_ANNOTATION_VERSION=1.3.2
JUNIT_VERSION=5.7.2
KOTLINX_COROUTINES_VERSION=1.5.1
KOTLIN_VERSION=1.5.10
MOCKITO_KOTLIN_VERSION=2.2.0
MOCKITO_VERSION=3.11.1
OKHTTP_VERSION=3.8.0
OKIO_VERSION=1.17.5
PROTOC_VERSION=3.14.0
ZCASH_WALLET_PLUGINS_VERSION=1.0.1
# This shouldn't be changed, as Android doesn't support targets beyond Java 8
ANDROID_JVM_TARGET=1.8

View File

@ -1,248 +0,0 @@
loadConfig('config.gradle')
// Publishing settings
project.group = config.publish.group
project.version = config.publish.versionName
project.ext.POM_ARTIFACT_ID = config.publish.artifactId
apply from: 'custom-tasks.gradle'
apply from: "ktlint.gradle"
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-allopen'
apply plugin: 'org.jetbrains.dokka'
apply plugin: 'com.google.protobuf'
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
apply plugin: 'com.vanniktech.maven.publish'
android {
compileSdkVersion Integer.parseInt(project.property("compileSdkVersion"))
useLibrary 'android.test.runner'
ndkVersion project.property("ndkVersion")
defaultConfig {
minSdkVersion Integer.parseInt(project.property("minSdkVersion"))
targetSdkVersion Integer.parseInt(project.property("targetSdkVersion"))
versionCode = config.publish.versionCode
versionName = config.publish.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
multiDexEnabled true
archivesBaseName = "zcash-android-sdk-${config.publish.name}"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
buildTypes {
debug {
// for test builds, which exceed the dex limit because they pull in things like mockito and grpc-testing
multiDexEnabled true
minifyEnabled false
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
release {
multiDexEnabled false
minifyEnabled false
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
sourceSets {
main {
java {
srcDirs "build/generated/source/grpc"
}
proto {
srcDir 'src/main/proto'
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// ExperimentalCoroutinesApi and FlowPreview help to clear the build warnings
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.FlowPreview"
// Tricky: fix: By default, the kotlin_module name will not include the version (in classes.jar/META-INF). Instead it has a colon, which breaks compilation on Windows. This is one way to set it explicitly to the proper value. See https://github.com/zcash/zcash-android-wallet-sdk/issues/222 for more info.
freeCompilerArgs += ["-module-name", "${config.publish.artifactId}-${config.publish.versionName}_${config.publish.target}"]
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LICENSE.md'
exclude 'META-INF/LICENSE-notice.md'
}
lintOptions {
baseline file("lint-baseline.xml")
}
}
mavenPublish {
androidVariantToPublish = config.publish.target
}
allOpen {
// marker for classes that we want to be able to extend in debug builds for testing purposes
annotation 'cash.z.ecc.android.sdk.annotation.OpenClass'
}
clean {
delete "$project.projectDir/src/generated/source/grpc"
}
dokkaHtml.configure {
dokkaSourceSets {
configureEach {
outputDirectory.set(file("build/docs/rtd"))
displayName.set("Zcash Android SDK")
includes.from("packages.md")
// samples.from("samples/basic.kt", "samples/advanced.kt")
}
}
}
protobuf {
generatedFilesBaseDir = "$projectDir/src/generated/source/grpc"
protoc { artifact = 'com.google.protobuf:protoc:3.14.0' }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.37.0" }
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
}
}
task.plugins {
grpc {
option 'lite'
}
}
}
}
}
cargo {
module = "."
libname = "zcashwalletsdk"
targets = [
"arm",
"arm64",
"x86",
"x86_64"
]
profile = "release"
prebuiltToolchains = true
}
dependencies {
implementation AndroidX.appCompat
// Architecture Components: Lifecycle
implementation AndroidX.lifecycle.runtimeKtx
implementation AndroidX.lifecycle.commonJava8
// Architecture Components: Room
implementation AndroidX.room.ktx
implementation AndroidX.paging.runtimeKtx
kapt AndroidX.room.compiler
// Kotlin
implementation Kotlin.stdlib.jdk8
implementation KotlinX.coroutines.core
implementation KotlinX.coroutines.android
// grpc-java
implementation "io.grpc:grpc-okhttp:_"
implementation "io.grpc:grpc-android:_"
implementation "io.grpc:grpc-protobuf-lite:_"
implementation "io.grpc:grpc-stub:_"
compileOnly 'javax.annotation:javax.annotation-api:_'
//
// Locked Versions
// these should be checked regularly and removed when possible
// 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:30.0-android'
// Transitive dependencies used because they're already necessary for other libraries
// GSON is available as a transitive dependency from several places so we use it for processing
// checkpoints but also document that by explicitly including here. If dependencies like Room
// or grpc-okhttp stop including GSON, then we should switch to something else for parsing JSON.
implementation 'com.google.code.gson:gson:2.8.6'
// OKIO is a transitive dependency used when writing param files to disk. Like GSON, this can be
// replaced if needed. For compatibility, we match the library version used in grpc-okhttp:
// https://github.com/grpc/grpc-java/blob/v1.37.x/build.gradle#L159
implementation 'com.squareup.okio:okio:1.17.5'
// Tests
testImplementation 'androidx.multidex:multidex:_'
testImplementation "org.jetbrains.kotlin:kotlin-reflect:_"
testImplementation 'org.mockito:mockito-junit-jupiter:_'
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:_'
testImplementation "org.junit.jupiter:junit-jupiter-api:_"
testImplementation "org.junit.jupiter:junit-jupiter-engine:_"
testImplementation "org.junit.jupiter:junit-jupiter-migrationsupport:_"
testImplementation "io.grpc:grpc-testing:_"
// NOTE: androidTests will use JUnit4, while src/test/java tests will leverage Junit5
// Attempting to use JUnit5 via https://github.com/mannodermaus/android-junit5 was painful. The plugin configuration
// was buggy, crashing in several places. It also would require a separate test flavor because it's minimum API 26
// because "JUnit 5 uses Java 8-specific APIs that didn't exist on Android before the Oreo release."
androidTestImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:_'
androidTestImplementation 'org.mockito:mockito-android:_'
androidTestImplementation "androidx.test:runner:_"
androidTestImplementation 'com.android.support:support-annotations:_'
androidTestImplementation "androidx.test:core:_"
androidTestImplementation "androidx.arch.core:core-testing:_"
androidTestImplementation 'androidx.test.ext:junit:_'
androidTestImplementation 'ru.gildor.coroutines:kotlin-coroutines-okhttp:_'
// used by 'ru.gildor.coroutines.okhttp.await' (to make simple suspended requests) and breaks on versions higher than 3.8.0
androidTestImplementation "com.squareup.okhttp3:okhttp:3.8.0"
// sample mnemonic plugin
androidTestImplementation 'com.github.zcash:zcash-android-wallet-plugins:_'
androidTestImplementation 'cash.z.ecc.android:kotlin-bip39:_'
}
//taskTree{
// noRepeat = true //do not print a sub-tree in the task-tree more than once
// impliesSubProjects = true //do not print task-tree for child projects in a multi-project
// taskDepth = 2 // limit tree depth to 3. Equivalent to running with the --task-depth option.
//}
preBuild.dependsOn('ktlintFormat')
preBuild.dependsOn('ktlint')
preBuild.dependsOn includeDirBugFix
//check.dependsOn dependencyCheckAggregate
def loadConfig(fileName) {
def config = new ConfigSlurper().parse(file(fileName).toURL())
project.ext.config = config
}

237
sdk-lib/build.gradle.kts Normal file
View File

@ -0,0 +1,237 @@
import com.google.protobuf.gradle.generateProtoTasks
import com.google.protobuf.gradle.id
import com.google.protobuf.gradle.plugins
import com.google.protobuf.gradle.proto
import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc
plugins {
id("com.android.library")
id("zcash.android-build-conventions")
kotlin("android")
kotlin("kapt")
id("org.jetbrains.kotlin.plugin.allopen")
id("org.jetbrains.dokka")
id("com.google.protobuf")
id("org.mozilla.rust-android-gradle.rust-android")
id("com.vanniktech.maven.publish")
}
// Publishing information
val ARTIFACT_ID = project.property("POM_ARTIFACT_ID").toString()
project.group = "cash.z.ecc.android"
project.version = project.property("LIBRARY_VERSION").toString()
publishing {
publications {
publications.withType<MavenPublication>().all {
artifactId = ARTIFACT_ID
}
}
}
android {
useLibrary("android.test.runner")
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
argument("room.schemaLocation", "$projectDir/schemas")
}
}
}
buildTypes {
getByName("debug").apply {
// test builds exceed the dex limit because they pull in large test libraries
multiDexEnabled = true
isMinifyEnabled = false
proguardFiles.addAll(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
File("proguard-rules.pro")
)
)
}
getByName("release").apply {
multiDexEnabled = false
isMinifyEnabled = project.property("IS_MINIFY_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
File("proguard-rules.pro")
)
)
}
}
sourceSets.getByName("main") {
java.srcDir("build/generated/source/grpc")
proto { srcDir("src/main/proto") }
}
kotlinOptions {
jvmTarget = libs.versions.java.get()
allWarningsAsErrors = project.property("IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.FlowPreview"
// Tricky: fix: By default, the kotlin_module name will not include the version (in classes.jar/META-INF). Instead it has a colon, which breaks compilation on Windows. This is one way to set it explicitly to the proper value. See https://github.com/zcash/zcash-android-wallet-sdk/issues/222 for more info.
freeCompilerArgs += listOf("-module-name", "$ARTIFACT_ID-${project.version}_release")
}
packagingOptions {
resources.excludes.addAll(
listOf(
"META-INF/DEPENDENCIES",
"META-INF/LICENSE",
"META-INF/LICENSE.txt",
"META-INF/license.txt",
"META-INF/NOTICE",
"META-INF/NOTICE.txt",
"META-INF/notice.txt",
"META-INF/ASL2.0",
"META-INF/LICENSE.md",
"META-INF/LICENSE-notice.md"
)
)
}
lint {
baseline(File("lint-baseline.xml"))
}
}
mavenPublish {
androidVariantToPublish = "release"
}
allOpen {
// marker for classes that we want to be able to extend in debug builds for testing purposes
annotation("cash.z.ecc.android.sdk.annotation.OpenClass")
}
tasks.dokkaHtml.configure {
dokkaSourceSets {
configureEach {
outputDirectory.set(file("build/docs/rtd"))
displayName.set("Zcash Android SDK")
includes.from("packages.md")
}
}
}
protobuf {
//generatedFilesBaseDir = "$projectDir/src/generated/source/grpc"
protoc { artifact = libs.protoc.get().asCoordinateString() }
plugins {
id("grpc") {
artifact = libs.grpc.protoc.get().asCoordinateString()
}
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
id("java") {
option("lite")
}
}
task.plugins {
id("grpc") {
option("lite")
}
}
}
}
}
cargo {
module = "."
libname = "zcashwalletsdk"
targets = listOf(
"arm",
"arm64",
"x86",
"x86_64"
)
profile = "release"
prebuiltToolchains = true
}
dependencies {
implementation(libs.androidx.annotation)
implementation(libs.androidx.appcompat)
// Architecture Components: Lifecycle
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.common)
// Architecture Components: Room
implementation(libs.androidx.room.core)
implementation(libs.androidx.paging)
kapt(libs.androidx.room.compiler)
// Kotlin
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
// grpc-java
implementation(libs.bundles.grpc)
compileOnly(libs.javax.annotation)
//
// Locked Versions
// these should be checked regularly and removed when possible
// 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(libs.guava)
// Transitive dependencies used because they're already necessary for other libraries
// GSON is available as a transitive dependency from several places so we use it for processing
// checkpoints but also document that by explicitly including here. If dependencies like Room
// or grpc-okhttp stop including GSON, then we should switch to something else for parsing JSON.
implementation(libs.gson)
// OKIO is a transitive dependency used when writing param files to disk. Like GSON, this can be
// replaced if needed. For compatibility, we match the library version used in grpc-okhttp:
// https://github.com/grpc/grpc-java/blob/v1.37.x/build.gradle#L159
implementation(libs.okio)
// Tests
testImplementation(libs.kotlin.reflect)
testImplementation(libs.mockito.junit)
testImplementation(libs.mockito.kotlin)
testImplementation(libs.bundles.junit)
testImplementation(libs.grpc.testing)
// NOTE: androidTests will use JUnit4, while src/test/java tests will leverage Junit5
// Attempting to use JUnit5 via https://github.com/mannodermaus/android-junit5 was painful. The plugin configuration
// was buggy, crashing in several places. It also would require a separate test flavor because it's minimum API 26
// because "JUnit 5 uses Java 8-specific APIs that didn't exist on Android before the Oreo release."
androidTestImplementation(libs.androidx.multidex)
androidTestImplementation(libs.mockito.kotlin)
androidTestImplementation(libs.mockito.android)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.coroutines.okhttp)
// used by 'ru.gildor.corutines.okhttp.await' (to make simple suspended requests) and breaks on versions higher than 3.8.0
androidTestImplementation(libs.okhttp)
// sample mnemonic plugin
androidTestImplementation(libs.zcashwalletplgn)
androidTestImplementation(libs.bip39)
}
tasks.getByName("preBuild").dependsOn(tasks.create("bugfixTask") {
doFirst {
mkdir("build/extracted-include-protos/main")
}
})
project.afterEvaluate {
val cargoTask = tasks.getByName("cargoBuild")
tasks.getByName("javaPreCompileDebug").dependsOn(cargoTask)
tasks.getByName("javaPreCompileRelease").dependsOn(cargoTask)
}
fun MinimalExternalModuleDependency.asCoordinateString() = "${module.group}:${module.name}:${versionConstraint.displayName}"

View File

@ -1,11 +0,0 @@
/////////////////////////////////////////
// Publishing
/////////////////////////////////////////
publish {
group = 'cash.z.ecc.android'
versionName = '1.3.0-beta18'
versionCode = 1_03_00_218 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
artifactId = 'zcash-android-sdk'
target = 'release'
}

View File

@ -1,7 +0,0 @@
def protoIncludeDir = "build/extracted-include-protos/main"
tasks.register("includeDirBugFix") {
doFirst {
mkdir(protoIncludeDir)
}
}

View File

@ -1,21 +0,0 @@
configurations {
ktlint
}
dependencies {
ktlint "com.pinterest:ktlint:0.40.0"
}
task ktlint(type: org.gradle.api.tasks.JavaExec, group: "verification") {
description = "Verifying Kotlin code style.."
classpath = configurations.ktlint
main = "com.pinterest.ktlint.Main"
args "-F", "src/**/*.kt", "--editorconfig=${rootProject.file(".editorconfig")}"
}
task ktlintFormat(type: org.gradle.api.tasks.JavaExec, group: "formatting") {
description = "Format Kotlin code style deviations."
classpath = configurations.ktlint
main = "com.pinterest.ktlint.Main"
args "-F", "src/**/*.kt", "--editorconfig=${rootProject.file(".editorconfig")}"
}

View File

@ -1,6 +1,6 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@ -10,6 +10,7 @@ import com.google.gson.Gson
import com.google.gson.stream.JsonReader
import java.io.IOException
import java.io.InputStreamReader
import java.util.Locale
/**
* Tool for loading checkpoints for the wallet, based on the height at which the wallet was born.
@ -73,7 +74,7 @@ class WalletBirthdayTool(appContext: Context) {
*/
@VisibleForTesting
internal fun birthdayDirectory(network: ZcashNetwork) =
"saplingtree/${network.networkName.lowercase()}"
"saplingtree/${(network.networkName as java.lang.String).toLowerCase(Locale.US)}"
internal fun birthdayHeight(fileName: String) = fileName.split('.').first().toInt()

View File

@ -1,13 +1,27 @@
enableFeaturePreview("VERSION_CATALOGS")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
repositories {
gradlePluginPortal()
google()
}
}
plugins {
id("de.fayard.refreshVersions") version("0.20.0")
plugins {
val detektVersion = extra["DETEKT_VERSION"].toString()
val dokkaVersion = extra["DOKKA_VERSION"].toString()
val gradleVersionsPluginVersion = extra["GRADLE_VERSIONS_PLUGIN_VERSION"].toString()
val kotlinVersion = extra["KOTLIN_VERSION"].toString()
val owaspVersion = extra["OWASP_DEPENDENCY_CHECK_VERSION"].toString()
val protobufVersion = extra["PROTOBUF_GRADLE_PLUGIN_VERSION"].toString()
id("com.github.ben-manes.versions") version (gradleVersionsPluginVersion) apply (false)
id("com.google.protobuf") version (protobufVersion) apply (false)
id("io.gitlab.arturbosch.detekt") version (detektVersion) apply (false)
id("org.jetbrains.dokka") version (dokkaVersion) apply (false)
id("org.jetbrains.kotlin.plugin.allopen") version (kotlinVersion) apply (false)
id("org.owasp.dependencycheck") version (owaspVersion) apply (false)
}
}
dependencyResolutionManagement {
@ -15,10 +29,149 @@ dependencyResolutionManagement {
google()
mavenCentral()
maven("https://jitpack.io")
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
}
@Suppress("UnstableApiUsage", "MaxLineLength")
versionCatalogs {
create("libs") {
val androidGradlePluginVersion = extra["ANDROID_GRADLE_PLUGIN_VERSION"].toString()
val androidxAnnotationVersion = extra["ANDROIDX_ANNOTATION_VERSION"].toString()
val androidxAppcompatVersion = extra["ANDROIDX_APPCOMPAT_VERSION"].toString()
val androidxConstraintLayoutVersion = extra["ANDROIDX_CONSTRAINT_LAYOUT_VERSION"].toString()
val androidxCoreVersion = extra["ANDROIDX_CORE_VERSION"].toString()
val androidxEspressoVersion = extra["ANDROIDX_ESPRESSO_VERSION"].toString()
val androidxLifecycleVersion = extra["ANDROIDX_LIFECYCLE_VERSION"].toString()
val androidxMultidexVersion = extra["ANDROIDX_MULTIDEX_VERSION"].toString()
val androidxNavigationVersion = extra["ANDROIDX_NAVIGATION_VERSION"].toString()
val androidxPagingVersion = extra["ANDROIDX_PAGING_VERSION"].toString()
val androidxRoomVersion = extra["ANDROIDX_ROOM_VERSION"].toString()
val androidxTestJunitVersion = extra["ANDROIDX_TEST_JUNIT_VERSION"].toString()
val androidxTestOrchestratorVersion = extra["ANDROIDX_ESPRESSO_VERSION"].toString()
val androidxTestVersion = extra["ANDROIDX_TEST_VERSION"].toString()
val androidxUiAutomatorVersion = extra["ANDROIDX_UI_AUTOMATOR_VERSION"].toString()
val bip39Version = extra["BIP39_VERSION"].toString()
val coroutinesOkhttpVersion = extra["COROUTINES_OKHTTP"].toString()
val googleMaterialVersion = extra["GOOGLE_MATERIAL_VERSION"].toString()
val grpcVersion = extra["GRPC_VERSION"].toString()
val gsonVersion = extra["GSON_VERSION"].toString()
val guavaVersion = extra["GUAVA_VERSION"].toString()
val javaVersion = extra["ANDROID_JVM_TARGET"].toString()
val javaxAnnotationVersion = extra["JAVAX_ANNOTATION_VERSION"].toString()
val junitVersion = extra["JUNIT_VERSION"].toString()
val kotlinVersion = extra["KOTLIN_VERSION"].toString()
val kotlinxCoroutinesVersion = extra["KOTLINX_COROUTINES_VERSION"].toString()
val mavenPublishGradlePluginVersion = extra["MAVEN_PUBLISH_GRADLE_PLUGIN"].toString()
val mockitoKotlinVersion = extra["MOCKITO_KOTLIN_VERSION"].toString()
val mockitoVersion = extra["MOCKITO_VERSION"].toString()
val okhttpVersion = extra["OKHTTP_VERSION"].toString()
val okioVersion = extra["OKIO_VERSION"].toString()
val protocVersion = extra["PROTOC_VERSION"].toString()
val rustGradlePluginVersion = extra["RUST_GRADLE_PLUGIN_VERSION"].toString()
val zcashWalletPluginVersion = extra["ZCASH_WALLET_PLUGINS_VERSION"].toString()
// Standalone versions
version("grpc", grpcVersion)
version("java", javaVersion)
version("protoc", protocVersion)
// Aliases
// Gradle plugins
alias("gradle-plugin-android").to("com.android.tools.build:gradle:$androidGradlePluginVersion")
alias("gradle-plugin-navigation").to("androidx.navigation:navigation-safe-args-gradle-plugin:$androidxNavigationVersion")
alias("gradle-plugin-publish").to("com.vanniktech:gradle-maven-publish-plugin:$mavenPublishGradlePluginVersion")
alias("gradle-plugin-rust").to("org.mozilla.rust-android-gradle:plugin:$rustGradlePluginVersion")
// Special cases used by the grpc gradle plugin
alias("grpc-protoc").to("io.grpc:protoc-gen-grpc-java:$grpcVersion")
alias("protoc").to("com.google.protobuf:protoc:$protocVersion")
// Libraries
alias("androidx-annotation").to("androidx.annotation:annotation:$androidxAnnotationVersion")
alias("androidx-appcompat").to("androidx.appcompat:appcompat:$androidxAppcompatVersion")
alias("androidx-constraintlayout").to("androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion")
alias("androidx-core").to("androidx.core:core-ktx:$androidxCoreVersion")
alias("androidx-lifecycle-common").to("androidx.lifecycle:lifecycle-common-java8:$androidxLifecycleVersion")
alias("androidx-lifecycle-runtime").to("androidx.lifecycle:lifecycle-runtime-ktx:$androidxLifecycleVersion")
alias("androidx-multidex").to("androidx.multidex:multidex:$androidxMultidexVersion")
alias("androidx-navigation-fragment").to("androidx.navigation:navigation-fragment-ktx:$androidxNavigationVersion")
alias("androidx-navigation-ui").to("androidx.navigation:navigation-ui-ktx:$androidxNavigationVersion")
alias("androidx-paging").to("androidx.paging:paging-runtime-ktx:$androidxPagingVersion")
alias("androidx-room-compiler").to("androidx.room:room-compiler:$androidxRoomVersion")
alias("androidx-room-core").to("androidx.room:room-ktx:$androidxRoomVersion")
alias("bip39").to("cash.z.ecc.android:kotlin-bip39:$bip39Version")
alias("grpc-android").to("io.grpc:grpc-android:$grpcVersion")
alias("grpc-okhttp").to("io.grpc:grpc-okhttp:$grpcVersion")
alias("grpc-protobuf").to("io.grpc:grpc-protobuf-lite:$grpcVersion")
alias("grpc-stub").to("io.grpc:grpc-stub:$grpcVersion")
alias("gson").to("com.google.code.gson:gson:$gsonVersion")
alias("guava").to("com.google.guava:guava:$guavaVersion")
alias("javax-annotation").to("javax.annotation:javax.annotation-api:$javaxAnnotationVersion")
alias("kotlin-reflect").to("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
alias("kotlin-stdlib").to("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
alias("kotlinx-coroutines-android").to("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxCoroutinesVersion")
alias("kotlinx-coroutines-core").to("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
alias("material").to("com.google.android.material:material:$googleMaterialVersion")
alias("okhttp").to("com.squareup.okhttp3:okhttp:$okhttpVersion")
alias("okio").to("com.squareup.okio:okio:$okioVersion")
alias("zcashwalletplgn").to("com.github.zcash:zcash-android-wallet-plugins:$zcashWalletPluginVersion")
// Test libraries
alias("androidx-espresso-contrib").to("androidx.test.espresso:espresso-contrib:$androidxEspressoVersion")
alias("androidx-espresso-core").to("androidx.test.espresso:espresso-core:$androidxEspressoVersion")
alias("androidx-espresso-intents").to("androidx.test.espresso:espresso-intents:$androidxEspressoVersion")
alias("androidx-test-core").to("androidx.test:core:$androidxTestVersion")
alias("androidx-test-junit").to("androidx.test.ext:junit:$androidxTestJunitVersion")
alias("androidx-test-runner").to("androidx.test:runner:$androidxTestVersion")
alias("androidx-testOrchestrator").to("androidx.test:orchestrator:$androidxTestOrchestratorVersion")
alias("androidx-uiAutomator").to("androidx.test.uiautomator:uiautomator-v18:$androidxUiAutomatorVersion")
alias("coroutines-okhttp").to("ru.gildor.coroutines:kotlin-coroutines-okhttp:$coroutinesOkhttpVersion")
alias("grpc-testing").to("io.grpc:grpc-testing:$grpcVersion")
alias("junit-api").to("org.junit.jupiter:junit-jupiter-api:$junitVersion")
alias("junit-engine").to("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
alias("junit-migration").to("org.junit.jupiter:junit-jupiter-migrationsupport:$junitVersion")
alias("kotlinx-coroutines-test").to("org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesVersion")
alias("mockito-android").to("org.mockito:mockito-android:$mockitoVersion")
alias("mockito-junit").to("org.mockito:mockito-junit-jupiter:$mockitoVersion")
alias("mockito-kotlin").to("com.nhaarman.mockitokotlin2:mockito-kotlin:$mockitoKotlinVersion")
// Bundles
bundle(
"androidx-test",
listOf(
"androidx-espresso-core",
"androidx-espresso-intents",
"androidx-espresso-contrib",
"androidx-test-junit",
"androidx-test-core"
)
)
bundle(
"grpc",
listOf(
"grpc-okhttp",
"grpc-android",
"grpc-protobuf",
"grpc-stub"
)
)
bundle(
"junit",
listOf(
"junit-api",
"junit-engine",
"junit-migration",
)
)
}
}
}
rootProject.name = "zcash-android-sdk"
includeBuild("build-conventions")
include("sdk-lib")
include("demo-app")

797
tools/detekt.yml Normal file
View File

@ -0,0 +1,797 @@
build:
maxIssues: 0
excludeCorrectable: false
weights:
# complexity: 2
# LongParameterList: 1
# style: 1
# comments: 1
config:
validation: true
warningsAsErrors: false
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
excludes: ''
processors:
active: true
exclude:
- 'DetektProgressListener'
# - 'KtFileCountProcessor'
# - 'PackageCountProcessor'
# - 'ClassCountProcessor'
# - 'FunctionCountProcessor'
# - 'PropertyCountProcessor'
# - 'ProjectComplexityProcessor'
# - 'ProjectCognitiveComplexityProcessor'
# - 'ProjectLLOCProcessor'
# - 'ProjectCLOCProcessor'
# - 'ProjectLOCProcessor'
# - 'ProjectSLOCProcessor'
# - 'LicenseHeaderLoaderExtension'
console-reports:
active: true
exclude:
- 'ProjectStatisticsReport'
- 'ComplexityReport'
- 'NotificationReport'
# - 'FindingsReport'
- 'FileBasedFindingsReport'
output-reports:
active: true
exclude:
# - 'TxtOutputReport'
# - 'XmlOutputReport'
# - 'HtmlOutputReport'
comments:
active: true
AbsentOrWrongFileLicense:
active: false
licenseTemplateFile: 'license.template'
licenseTemplateIsRegex: false
CommentOverPrivateFunction:
active: false
CommentOverPrivateProperty:
active: false
DeprecatedBlockTag:
active: false
EndOfSentenceFormat:
active: false
endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
UndocumentedPublicClass:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
searchInNestedClass: true
searchInInnerClass: true
searchInInnerObject: true
searchInInnerInterface: true
UndocumentedPublicFunction:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
UndocumentedPublicProperty:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
complexity:
active: true
ComplexCondition:
active: true
threshold: 4
ComplexInterface:
active: false
threshold: 10
includeStaticDeclarations: false
includePrivateDeclarations: false
ComplexMethod:
active: true
threshold: 15
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
ignoreNestingFunctions: false
nestingFunctions:
- 'also'
- 'apply'
- 'forEach'
- 'isNotNull'
- 'ifNull'
- 'let'
- 'run'
- 'use'
- 'with'
LabeledExpression:
active: false
ignoredLabels: []
LargeClass:
active: true
threshold: 600
LongMethod:
active: true
threshold: 60
ignoreAnnotated: []
LongParameterList:
active: true
functionThreshold: 6
constructorThreshold: 7
ignoreDefaultParameters: false
ignoreDataClasses: true
ignoreAnnotated: []
MethodOverloading:
active: false
threshold: 6
NamedArguments:
active: false
threshold: 3
NestedBlockDepth:
active: true
threshold: 4
ReplaceSafeCallChainWithRun:
active: false
StringLiteralDuplication:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
threshold: 3
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
thresholdInObjects: 11
thresholdInEnums: 11
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false
coroutines:
active: true
GlobalCoroutineUsage:
active: false
RedundantSuspendModifier:
active: false
SleepInsteadOfDelay:
active: false
SuspendFunWithFlowReturnType:
active: false
empty-blocks:
active: true
EmptyCatchBlock:
active: true
allowedExceptionNameRegex: '_|(ignore|expected).*'
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
active: true
EmptyDoWhileBlock:
active: true
EmptyElseBlock:
active: true
EmptyFinallyBlock:
active: true
EmptyForBlock:
active: true
EmptyFunctionBlock:
active: true
ignoreOverridden: false
EmptyIfBlock:
active: true
EmptyInitBlock:
active: true
EmptyKtFile:
active: true
EmptySecondaryConstructor:
active: true
EmptyTryBlock:
active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
active: true
exceptions:
active: true
ExceptionRaisedInUnexpectedLocation:
active: true
methodNames:
- 'equals'
- 'finalize'
- 'hashCode'
- 'toString'
InstanceOfCheckForException:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
NotImplementedDeclaration:
active: false
ObjectExtendsThrowable:
active: false
PrintStackTrace:
active: true
RethrowCaughtException:
active: true
ReturnFromFinally:
active: true
ignoreLabeled: false
SwallowedException:
active: true
ignoredExceptionTypes:
- 'InterruptedException'
- 'MalformedURLException'
- 'NumberFormatException'
- 'ParseException'
allowedExceptionNameRegex: '_|(ignore|expected).*'
ThrowingExceptionFromFinally:
active: true
ThrowingExceptionInMain:
active: false
ThrowingExceptionsWithoutMessageOrCause:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
exceptions:
- 'ArrayIndexOutOfBoundsException'
- 'Exception'
- 'IllegalArgumentException'
- 'IllegalMonitorStateException'
- 'IllegalStateException'
- 'IndexOutOfBoundsException'
- 'NullPointerException'
- 'RuntimeException'
- 'Throwable'
ThrowingNewInstanceOfSameException:
active: true
TooGenericExceptionCaught:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
exceptionNames:
- 'ArrayIndexOutOfBoundsException'
- 'Error'
- 'Exception'
- 'IllegalMonitorStateException'
- 'IndexOutOfBoundsException'
- 'NullPointerException'
- 'RuntimeException'
- 'Throwable'
allowedExceptionNameRegex: '_|(ignore|expected).*'
TooGenericExceptionThrown:
active: true
exceptionNames:
- 'Error'
- 'Exception'
- 'RuntimeException'
- 'Throwable'
formatting:
active: true
android: false
autoCorrect: true
AnnotationOnSeparateLine:
active: false
autoCorrect: true
AnnotationSpacing:
active: false
autoCorrect: true
ArgumentListWrapping:
active: false
autoCorrect: true
indentSize: 4
maxLineLength: 120
ChainWrapping:
active: true
autoCorrect: true
CommentSpacing:
active: true
autoCorrect: true
EnumEntryNameCase:
active: false
autoCorrect: true
Filename:
active: true
FinalNewline:
active: true
autoCorrect: true
insertFinalNewLine: true
ImportOrdering:
active: false
autoCorrect: true
layout: '*,java.**,javax.**,kotlin.**,^'
Indentation:
active: false
autoCorrect: true
indentSize: 4
continuationIndentSize: 4
MaximumLineLength:
active: true
maxLineLength: 120
ignoreBackTickedIdentifier: false
ModifierOrdering:
active: true
autoCorrect: true
MultiLineIfElse:
active: true
autoCorrect: true
NoBlankLineBeforeRbrace:
active: true
autoCorrect: true
NoConsecutiveBlankLines:
active: true
autoCorrect: true
NoEmptyClassBody:
active: true
autoCorrect: true
NoEmptyFirstLineInMethodBlock:
active: false
autoCorrect: true
NoLineBreakAfterElse:
active: true
autoCorrect: true
NoLineBreakBeforeAssignment:
active: true
autoCorrect: true
NoMultipleSpaces:
active: true
autoCorrect: true
NoSemicolons:
active: true
autoCorrect: true
NoTrailingSpaces:
active: true
autoCorrect: true
NoUnitReturn:
active: true
autoCorrect: true
NoUnusedImports:
active: true
autoCorrect: true
NoWildcardImports:
active: true
PackageName:
active: true
autoCorrect: true
ParameterListWrapping:
active: true
autoCorrect: true
indentSize: 4
maxLineLength: 120
SpacingAroundAngleBrackets:
active: false
autoCorrect: true
SpacingAroundColon:
active: true
autoCorrect: true
SpacingAroundComma:
active: true
autoCorrect: true
SpacingAroundCurly:
active: true
autoCorrect: true
SpacingAroundDot:
active: true
autoCorrect: true
SpacingAroundDoubleColon:
active: false
autoCorrect: true
SpacingAroundKeyword:
active: true
autoCorrect: true
SpacingAroundOperators:
active: true
autoCorrect: true
SpacingAroundParens:
active: true
autoCorrect: true
SpacingAroundRangeOperator:
active: true
autoCorrect: true
SpacingAroundUnaryOperator:
active: false
autoCorrect: true
SpacingBetweenDeclarationsWithAnnotations:
active: false
autoCorrect: true
SpacingBetweenDeclarationsWithComments:
active: false
autoCorrect: true
StringTemplate:
active: true
autoCorrect: true
naming:
active: true
BooleanPropertyNaming:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
allowedPattern: '^(is|has|are)'
ClassNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
classPattern: '[A-Z][a-zA-Z0-9]*'
ConstructorParameterNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
EnumNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
forbiddenName: []
FunctionMaxLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
maximumFunctionNameLength: 30
FunctionMinLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
minimumFunctionNameLength: 3
FunctionNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)'
excludeClassPattern: '$^'
ignoreOverridden: true
ignoreAnnotated:
- 'Composable'
FunctionParameterNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
parameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
InvalidPackageDeclaration:
active: false
excludes: ['**/*.kts']
rootPackage: ''
MatchingDeclarationName:
active: true
mustBeFirst: true
MemberNameEqualsClassName:
active: true
ignoreOverridden: true
NoNameShadowing:
active: false
NonBooleanPropertyPrefixedWithIs:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
ObjectPropertyNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
PackageNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
TopLevelPropertyNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
constantPattern: '[A-Z][_A-Z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
VariableMaxLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
maximumVariableNameLength: 64
VariableMinLength:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
minimumVariableNameLength: 1
VariableNaming:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
performance:
active: true
ArrayPrimitive:
active: true
ForEachOnRange:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
SpreadOperator:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
UnnecessaryTemporaryInstantiation:
active: true
potential-bugs:
active: true
AvoidReferentialEquality:
active: false
forbiddenTypePatterns:
- 'kotlin.String'
CastToNullableType:
active: false
Deprecation:
active: false
DontDowncastCollectionTypes:
active: false
DoubleMutabilityForCollection:
active: false
DuplicateCaseInWhenExpression:
active: true
EqualsAlwaysReturnsTrueOrFalse:
active: true
EqualsWithHashCodeExist:
active: true
ExitOutsideMain:
active: false
ExplicitGarbageCollectionCall:
active: true
HasPlatformType:
active: false
IgnoredReturnValue:
active: false
restrictToAnnotatedMethods: true
returnValueAnnotations:
- '*.CheckResult'
- '*.CheckReturnValue'
ignoreReturnValueAnnotations:
- '*.CanIgnoreReturnValue'
ImplicitDefaultLocale:
active: true
ImplicitUnitReturnType:
active: false
allowExplicitReturnType: true
InvalidRange:
active: true
IteratorHasNextCallsNextMethod:
active: true
IteratorNotThrowingNoSuchElementException:
active: true
LateinitUsage:
active: false
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
excludeAnnotatedProperties: []
ignoreOnClassesPattern: ''
MapGetWithNotNullAssertionOperator:
active: false
MissingWhenCase:
active: true
allowElseExpression: true
NullableToStringCall:
active: false
RedundantElseInWhen:
active: true
UnconditionalJumpStatementInLoop:
active: false
UnnecessaryNotNullOperator:
active: true
UnnecessarySafeCall:
active: true
UnreachableCatchBlock:
active: false
UnreachableCode:
active: true
UnsafeCallOnNullableType:
active: true
UnsafeCast:
active: true
UnusedUnaryOperator:
active: false
UselessPostfixExpression:
active: false
WrongEqualsTypeParameter:
active: true
style:
active: true
ClassOrdering:
active: false
CollapsibleIfStatements:
active: false
DataClassContainsFunctions:
active: false
conversionFunctionPrefix: 'to'
DataClassShouldBeImmutable:
active: false
DestructuringDeclarationWithTooManyEntries:
active: false
maxDestructuringEntries: 3
EqualsNullCall:
active: true
EqualsOnSignatureLine:
active: false
ExplicitCollectionElementAccessMethod:
active: false
ExplicitItLambdaParameter:
active: false
ExpressionBodySyntax:
active: false
includeLineWrapping: false
ForbiddenComment:
active: true
values:
- 'FIXME:'
- 'STOPSHIP:'
- 'TODO:'
allowedPatterns: '\[[^\]]\d+\]'
ForbiddenImport:
active: false
imports: []
forbiddenPatterns: ''
ForbiddenMethodCall:
active: false
methods:
- 'kotlin.io.print'
- 'kotlin.io.println'
ForbiddenPublicDataClass:
active: true
excludes: ['**']
ignorePackages:
- '*.internal'
- '*.internal.*'
ForbiddenVoid:
active: false
ignoreOverridden: false
ignoreUsageInGenerics: false
FunctionOnlyReturningConstant:
active: true
ignoreOverridableFunction: true
ignoreActualFunction: true
excludedFunctions: ''
excludeAnnotatedFunction:
- 'dagger.Provides'
LibraryCodeMustSpecifyReturnType:
active: true
excludes: ['**']
LibraryEntitiesShouldNotBePublic:
active: true
excludes: ['**']
LoopWithTooManyJumpStatements:
active: true
maxJumpCount: 1
MagicNumber:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
ignoreNumbers:
- '-1'
- '0'
- '1'
- '2'
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
ignoreLocalVariableDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreNamedArgument: true
ignoreEnums: false
ignoreRanges: false
ignoreExtensionFunctions: true
MandatoryBracesIfStatements:
active: false
MandatoryBracesLoops:
active: false
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: true
excludeImportStatements: true
excludeCommentStatements: false
MayBeConst:
active: true
ModifierOrder:
active: true
MultilineLambdaItParameter:
active: false
NestedClassesVisibility:
active: true
NewLineAtEndOfFile:
active: false
NoTabs:
active: false
ObjectLiteralToLambda:
active: false
OptionalAbstractKeyword:
active: true
OptionalUnit:
active: false
OptionalWhenBraces:
active: false
PreferToOverPairSyntax:
active: false
ProtectedMemberInFinalClass:
active: true
RedundantExplicitType:
active: false
RedundantHigherOrderMapUsage:
active: false
RedundantVisibilityModifierRule:
active: false
ReturnCount:
active: true
max: 2
excludedFunctions: 'equals'
excludeLabeled: false
excludeReturnFromLambda: true
excludeGuardClauses: false
SafeCast:
active: true
SerialVersionUIDInSerializableClass:
active: true
SpacingBetweenPackageAndImports:
active: false
ThrowsCount:
active: true
max: 2
excludeGuardClauses: false
TrailingWhitespace:
active: false
UnderscoresInNumericLiterals:
active: false
acceptableDecimalLength: 5
UnnecessaryAbstractClass:
active: true
excludeAnnotatedClasses:
- 'dagger.Module'
UnnecessaryAnnotationUseSiteTarget:
active: false
UnnecessaryApply:
active: true
UnnecessaryFilter:
active: false
UnnecessaryInheritance:
active: true
UnnecessaryLet:
active: false
UnnecessaryParentheses:
active: false
UntilInsteadOfRangeTo:
active: false
UnusedImports:
active: false
UnusedPrivateClass:
active: true
UnusedPrivateMember:
active: true
allowedNames: '(_|ignored|expected|serialVersionUID)'
UseArrayLiteralsInAnnotations:
active: false
UseCheckNotNull:
active: false
UseCheckOrError:
active: false
UseDataClass:
active: false
excludeAnnotatedClasses: []
allowVars: false
UseEmptyCounterpart:
active: false
UseIfEmptyOrIfBlank:
active: false
UseIfInsteadOfWhen:
active: false
UseIsNullOrEmpty:
active: false
UseOrEmpty:
active: false
UseRequire:
active: false
UseRequireNotNull:
active: false
UselessCallOnNotNull:
active: true
UtilityClassWithPublicConstructor:
active: true
VarCouldBeVal:
active: true
WildcardImport:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
excludeImports:
- 'java.util.*'
- 'kotlinx.android.synthetic.*'

View File

@ -1,147 +0,0 @@
#### Dependencies and Plugin versions with their available updates.
#### Generated by `./gradlew refreshVersions` version 0.20.0
####
#### Don't manually edit or split the comments that start with four hashtags (####),
#### they will be overwritten by refreshVersions.
####
#### suppress inspection "SpellCheckingInspection" for whole file
#### suppress inspection "UnusedProperty" for whole file
plugin.android=7.0.2
## # available=7.0.0-alpha01
## # available=7.0.0-alpha02
## # available=7.0.0-alpha03
## # available=7.0.0-alpha04
## # available=7.0.0-alpha05
## # available=7.0.0-alpha06
## # available=7.0.0-alpha07
## # available=7.0.0-alpha08
## # available=7.0.0-alpha09
## # available=7.0.0-alpha10
## # available=7.0.0-alpha11
## # available=7.0.0-alpha12
## # available=7.0.0-alpha13
## # available=7.0.0-alpha14
## # available=7.0.0-alpha15
## # available=7.0.0-beta01
## # available=7.0.0-beta02
## # available=7.0.0-beta03
## # available=7.0.0-beta04
## # available=7.1.0-alpha01
## # available=7.1.0-alpha02
version.androidx.appcompat=1.3.0
## # available=1.4.0-alpha01
## # available=1.4.0-alpha02
version.androidx.arch.core=2.1.0
version.androidx.lifecycle=2.3.1
## # available=2.4.0-alpha01
## # available=2.4.0-alpha02
version.androidx.multidex=2.0.1
version.androidx.navigation=2.3.5
## # available=2.4.0-alpha01
## # available=2.4.0-alpha02
## # available=2.4.0-alpha03
## # available=2.4.0-alpha04
## # available=2.4.0-alpha05
## # available=2.4.0-alpha06
## # available=2.4.0-alpha07
version.androidx.paging=2.1.2
## # available=3.0.0-alpha01
## # available=3.0.0-alpha02
## # available=3.0.0-alpha03
## # available=3.0.0-alpha04
## # available=3.0.0-alpha05
## # available=3.0.0-alpha06
## # available=3.0.0-alpha07
## # available=3.0.0-alpha08
## # available=3.0.0-alpha09
## # available=3.0.0-alpha10
## # available=3.0.0-alpha11
## # available=3.0.0-alpha12
## # available=3.0.0-alpha13
## # available=3.0.0-beta01
## # available=3.0.0-beta02
## # available=3.0.0-beta03
## # available=3.0.0-rc01
## # available=3.0.0
## # available=3.1.0-alpha01
version.androidx.room=2.3.0
## # available=2.4.0-alpha01
## # available=2.4.0-alpha02
## # available=2.4.0-alpha03
version.androidx.test=1.4.0-beta02
version.androidx.test.core=1.4.0-beta02
version.androidx.test.ext.junit=1.1.3-beta02
version.cash.z.ecc.android..kotlin-bip39=1.0.2
version.com.android.support..support-annotations=28.0.0
version.com.github.zcash..zcash-android-wallet-plugins=1.0.1
version.com.google.protobuf..protobuf-gradle-plugin=0.8.16
version.com.nhaarman.mockitokotlin2..mockito-kotlin=2.2.0
version.com.vanniktech..gradle-maven-publish-plugin=0.15.1
version.androidx.navigation..navigation-safe-args-gradle-plugin=2.3.0
version.io.grpc..grpc-android=1.38.1
version.io.grpc..grpc-okhttp=1.38.1
version.io.grpc..grpc-protobuf-lite=1.38.1
version.io.grpc..grpc-stub=1.38.1
version.io.grpc..grpc-testing=1.38.1
version.javax.annotation..javax.annotation-api=1.3.2
version.junit=5.7.2
### available=5.8.0-M1
version.kotlin=1.5.10
## # available=1.5.20-M1
## # available=1.5.20-RC
version.kotlinx.coroutines=1.5.0
version.mockito=3.11.1
version.org.jetbrains.dokka..dokka-gradle-plugin=1.4.32
version.org.junit.jupiter..junit-jupiter-api=5.7.2
## # available=5.7.2
## # available=5.8.0-M1
version.org.junit.jupiter..junit-jupiter-engine=5.7.2
## # available=5.7.2
## # available=5.8.0-M1
version.org.junit.jupiter..junit-jupiter-migrationsupport=5.7.2
## # available=5.7.2
## # available=5.8.0-M1
version.org.mockito..mockito-android=3.11.1
## # available=3.11.0
## # available=3.11.1
version.org.mockito..mockito-junit-jupiter=3.11.1
## # available=3.11.0
## # available=3.11.1
version.org.owasp..dependency-check-gradle=6.2.2
version.ru.gildor.coroutines..kotlin-coroutines-okhttp=1.0