[#880] Create sdk-incubator-lib

Add dependency link between lib and incubator

Make AndroidApiVersion internal in SDK
This commit is contained in:
Carter Jernigan 2023-02-06 09:41:38 -05:00 committed by Carter Jernigan
parent 8df7a5d3ec
commit 1c76ea6998
73 changed files with 443 additions and 222 deletions

1
.gitignore vendored
View File

@ -83,3 +83,4 @@ backup-dbs/
*.db
.DS_Store
/.idea/androidTestResultsUserPreferences.xml
/.idea/inspectionProfiles/Project_Default.xml

View File

@ -1,6 +1,10 @@
Change Log
==========
## 1.15.0-beta01
### Changed
- A new package `sdk-incubator-lib` is now available as a public API. This package contains experimental APIs that may be promoted to the SDK in the future. The APIs in this package are not guaranteed to be stable, and may change at any time.
## 1.14.0-beta01
### Changed
- The minimum supported version of Android is now API level 24.

View File

@ -10,6 +10,8 @@ pluginManager.withPlugin("com.android.application") {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
multiDexEnabled = true
// 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
@ -34,6 +36,8 @@ pluginManager.withPlugin("com.android.library") {
// This is deprecated but there isn't a replacement for it yet with instrumentation tests.
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
multiDexEnabled = true
// 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
@ -61,6 +65,8 @@ pluginManager.withPlugin("com.android.test") {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
multiDexEnabled = true
// 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
@ -85,6 +91,8 @@ fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
ndkVersion = project.property("ANDROID_NDK_VERSION").toString()
compileOptions {
isCoreLibraryDesugaringEnabled = true
val javaVersion = JavaVersion.toVersion(project.property("ANDROID_JVM_TARGET").toString())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
@ -139,6 +147,13 @@ fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
}
}
dependencies {
add(
"coreLibraryDesugaring",
"com.android.tools:desugar_jdk_libs:${project.property("CORE_LIBRARY_DESUGARING_VERSION")}"
)
}
if (this is CommonExtension<*, *, *, *>) {
kotlinOptions {
jvmTarget = project.property("ANDROID_JVM_TARGET").toString()

View File

@ -8,11 +8,6 @@ plugins {
android {
namespace = "cash.z.ecc.android.sdk.darkside"
defaultConfig {
//targetSdk = 30 //Integer.parseInt(project.property("targetSdkVersion"))
multiDexEnabled = true
}
buildTypes {
create("benchmark") {
// We provide the extra benchmark build type just for benchmarking purposes

View File

@ -101,6 +101,7 @@ android {
dependencies {
// SDK
implementation(projects.sdkLib)
implementation(projects.sdkIncubatorLib)
// sample mnemonic plugin
implementation(libs.zcashwalletplgn)

View File

@ -3,7 +3,7 @@
-renamesourcefileattribute SourceFile
# Strip out log messages
-assumenosideeffects public class cash.z.ecc.android.sdk.demoapp.util.Twig {
-assumenosideeffects public class cash.z.ecc.android.sdk.util.Twig {
public static *** verbose(...);
public static *** debug(...);
public static *** info(...);

View File

@ -1,19 +0,0 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
import cash.z.ecc.android.sdk.demoapp.model.WalletAddress
object WalletAddressFixture {
// These fixture values are derived from the secret defined in PersistableWalletFixture
// TODO [#161]: Pending SDK support
// TODO [#161]: https://github.com/zcash/secant-android-wallet/issues/161
const val UNIFIED_ADDRESS_STRING = "Unified GitHub Issue #161"
@Suppress("MaxLineLength")
const val SAPLING_ADDRESS_STRING = "zs1hf72k87gev2qnvg9228vn2xt97adfelju2hm2ap4xwrxkau5dz56mvkeseer3u8283wmy7skt4u"
const val TRANSPARENT_ADDRESS_STRING = "t1QZMTZaU1EwXppCLL5dR6U9y2M4ph3CSPK"
suspend fun unified() = WalletAddress.Unified.new(UNIFIED_ADDRESS_STRING)
suspend fun sapling() = WalletAddress.Sapling.new(SAPLING_ADDRESS_STRING)
suspend fun transparent() = WalletAddress.Transparent.new(TRANSPARENT_ADDRESS_STRING)
}

View File

@ -1,17 +0,0 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
import cash.z.ecc.android.sdk.demoapp.model.WalletAddress
import cash.z.ecc.android.sdk.demoapp.model.WalletAddresses
object WalletAddressesFixture {
suspend fun new(
unified: String = WalletAddressFixture.UNIFIED_ADDRESS_STRING,
sapling: String = WalletAddressFixture.SAPLING_ADDRESS_STRING,
transparent: String = WalletAddressFixture.TRANSPARENT_ADDRESS_STRING
) = WalletAddresses(
WalletAddress.Unified.new(unified),
WalletAddress.Sapling.new(sapling),
WalletAddress.Transparent.new(transparent)
)
}

View File

@ -1,15 +1,15 @@
package cash.z.ecc.android.sdk.demoapp
import androidx.multidex.MultiDexApplication
import cash.z.ecc.android.sdk.demoapp.util.Twig
import cash.z.ecc.android.sdk.internal.Twig2
class App : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
Twig.initialize(applicationContext)
Twig.info { "Starting application…" }
Twig2.initialize(applicationContext)
Twig2.info { "Starting application…" }
if (BuildConfig.DEBUG) {
StrictModeHelper.enableStrictMode()
@ -18,7 +18,7 @@ class App : MultiDexApplication() {
cash.z.ecc.android.sdk.internal.Twig.enabled(true)
} else {
// In release builds, logs should be stripped by R8 rules
Twig.assertLoggingStripped()
Twig2.assertLoggingStripped()
}
}
}

View File

@ -1,6 +1,7 @@
package cash.z.ecc.android.sdk.demoapp
import android.content.Context
import cash.z.ecc.android.sdk.WalletCoordinator
import cash.z.ecc.android.sdk.demoapp.preference.EncryptedPreferenceKeys
import cash.z.ecc.android.sdk.demoapp.preference.EncryptedPreferenceSingleton
import cash.z.ecc.android.sdk.demoapp.util.LazyWithArgument

View File

@ -2,9 +2,9 @@ package cash.z.ecc.android.sdk.demoapp.fixture
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.demoapp.model.PercentDecimal
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.SynchronizerError
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.WalletSnapshot
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi

View File

@ -1,9 +1,9 @@
package cash.z.ecc.android.sdk.demoapp.preference
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.demoapp.preference.api.PreferenceProvider
import cash.z.ecc.android.sdk.demoapp.preference.model.entry.Key
import cash.z.ecc.android.sdk.demoapp.preference.model.entry.PreferenceDefault
import cash.z.ecc.android.sdk.model.PersistableWallet
import org.json.JSONObject
data class PersistableWalletPreferenceDefault(

View File

@ -24,7 +24,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.demoapp.model.WalletAddresses
import cash.z.ecc.android.sdk.model.WalletAddresses
import kotlinx.coroutines.flow.flow
// @Preview

View File

@ -20,9 +20,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.demoapp.model.toZecString
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.WalletSnapshot
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.model.toZecString
// @Preview
// @Composable

View File

@ -2,8 +2,8 @@ package cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.demoapp.model.PercentDecimal
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi

View File

@ -6,26 +6,28 @@ import androidx.lifecycle.viewModelScope
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.WalletCoordinator
import cash.z.ecc.android.sdk.block.CompactBlockProcessor
import cash.z.ecc.android.sdk.demoapp.WalletCoordinator
import cash.z.ecc.android.sdk.demoapp.getInstance
import cash.z.ecc.android.sdk.demoapp.model.PercentDecimal
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.demoapp.model.WalletAddresses
import cash.z.ecc.android.sdk.demoapp.model.ZecSend
import cash.z.ecc.android.sdk.demoapp.model.send
import cash.z.ecc.android.sdk.demoapp.preference.EncryptedPreferenceKeys
import cash.z.ecc.android.sdk.demoapp.preference.EncryptedPreferenceSingleton
import cash.z.ecc.android.sdk.demoapp.ui.common.ANDROID_STATE_FLOW_TIMEOUT
import cash.z.ecc.android.sdk.demoapp.ui.common.throttle
import cash.z.ecc.android.sdk.demoapp.util.Twig
import cash.z.ecc.android.sdk.demoapp.util.fromResources
import cash.z.ecc.android.sdk.internal.Twig2
import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.PendingTransaction
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.PersistableWallet
import cash.z.ecc.android.sdk.model.WalletAddresses
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.model.ZecSend
import cash.z.ecc.android.sdk.model.isMined
import cash.z.ecc.android.sdk.model.isSubmitSuccess
import cash.z.ecc.android.sdk.model.send
import cash.z.ecc.android.sdk.tool.DerivationTool
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -140,7 +142,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
val application = getApplication<Application>()
viewModelScope.launch {
val newWallet = PersistableWallet.new(application)
val newWallet = PersistableWallet.new(application, ZcashNetwork.fromResources(application))
persistExistingWallet(newWallet)
}
}
@ -172,7 +174,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
synchronizer.send(spendingKey, zecSend)
}
} else {
Twig.info { "Unable to send funds" }
Twig2.info { "Unable to send funds" }
}
}
@ -189,7 +191,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
synchronizer.shieldFunds(spendingKey)
}
} else {
Twig.info { "Unable to shield funds" }
Twig2.info { "Unable to shield funds" }
}
}
@ -254,27 +256,27 @@ private fun Synchronizer.toCommonError(): Flow<SynchronizerError?> = callbackFlo
trySend(null)
onCriticalErrorHandler = {
Twig.error { "WALLET - Error Critical: $it" }
Twig2.error { "WALLET - Error Critical: $it" }
trySend(SynchronizerError.Critical(it))
false
}
onProcessorErrorHandler = {
Twig.error { "WALLET - Error Processor: $it" }
Twig2.error { "WALLET - Error Processor: $it" }
trySend(SynchronizerError.Processor(it))
false
}
onSubmissionErrorHandler = {
Twig.error { "WALLET - Error Submission: $it" }
Twig2.error { "WALLET - Error Submission: $it" }
trySend(SynchronizerError.Submission(it))
false
}
onSetupErrorHandler = {
Twig.error { "WALLET - Error Setup: $it" }
Twig2.error { "WALLET - Error Setup: $it" }
trySend(SynchronizerError.Setup(it))
false
}
onChainErrorHandler = { x, y ->
Twig.error { "WALLET - Error Chain: $x, $y" }
Twig2.error { "WALLET - Error Chain: $x, $y" }
trySend(SynchronizerError.Chain(x, y))
}

View File

@ -16,9 +16,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.demoapp.fixture.WalletFixture
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.demoapp.model.SeedPhrase
import cash.z.ecc.android.sdk.fixture.WalletFixture
import cash.z.ecc.android.sdk.model.PersistableWallet
import cash.z.ecc.android.sdk.model.SeedPhrase
import cash.z.ecc.android.sdk.model.ZcashNetwork
@Preview

View File

@ -33,18 +33,18 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.demoapp.fixture.WalletFixture
import cash.z.ecc.android.sdk.demoapp.model.Memo
import cash.z.ecc.android.sdk.demoapp.model.MonetarySeparators
import cash.z.ecc.android.sdk.demoapp.model.ZecSend
import cash.z.ecc.android.sdk.demoapp.model.ZecSendExt
import cash.z.ecc.android.sdk.demoapp.model.ZecString
import cash.z.ecc.android.sdk.demoapp.model.ZecStringExt
import cash.z.ecc.android.sdk.demoapp.model.toZecString
import cash.z.ecc.android.sdk.demoapp.ui.common.MINIMAL_WEIGHT
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.WalletSnapshot
import cash.z.ecc.android.sdk.demoapp.util.fromResources
import cash.z.ecc.android.sdk.fixture.WalletFixture
import cash.z.ecc.android.sdk.model.Memo
import cash.z.ecc.android.sdk.model.MonetarySeparators
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.model.ZecSend
import cash.z.ecc.android.sdk.model.ZecSendExt
import cash.z.ecc.android.sdk.model.ZecString
import cash.z.ecc.android.sdk.model.ZecStringExt
import cash.z.ecc.android.sdk.model.toZecString
// @Preview
// @Composable

View File

@ -4,7 +4,7 @@ import android.os.Build
import androidx.annotation.ChecksSdkIntAtLeast
import androidx.annotation.IntRange
object AndroidApiVersion {
internal object AndroidApiVersion {
/**
* @param sdk SDK version number to test against the current environment.
* @return `true` if [android.os.Build.VERSION.SDK_INT] is greater than or equal to

View File

@ -11,6 +11,7 @@ Thankfully, the only thing an app developer has to be concerned with is the foll
The SDK is broken down into several logical components, implemented as Gradle modules. At a high level, the modularization is:
* sdk-lib — Compiles all of the modules together for the SDK.
* sdk-incubator-lib — Incubator for new APIs that may eventually be promoted to the SDK. Classes are packaged to match the SDK, so that moving them will not necessarily change the API. While SDK clients can use classes in sdk-incubator-lib, they should anticipate a greater amount of public API churn.
* lightwallet-client-lib — Provides a set of Kotlin APIs for interacting with lightwalletd over the network.
* darkside-test-lib — Contains integration tests for the SDK, running against a localhost lightwalletd instance running in darkside mode. This is not run as part of the SDK test suite, because it requires some manual setup to enable.
* demo-app — Contains a primitive demo application to exercise the SDK.
@ -19,6 +20,8 @@ The SDK is broken down into several logical components, implemented as Gradle mo
flowchart TB;
lightwalletClientLib[[lightwallet-client-lib]] --> sdkLib[[sdk-lib]];
sdkLib[[sdk-lib]] --> demoApp[[demo-app]];
sdkLib[[sdk-lib]] --> sdkIncubatorLib[[sdk-incubator-lib]];
sdkIncubatorLib[[sdk-incubator-lib]] --> demoApp[[demo-app]];
sdkLib[[sdk-lib]] --> darksideTestLib[[darkside-test-lib]];
```

View File

@ -114,6 +114,7 @@ ANDROIDX_TEST_RUNNER_VERSION=1.5.0
ANDROIDX_TRACING_VERSION=1.2.0-alpha01
ANDROIDX_UI_AUTOMATOR_VERSION=2.3.0-alpha02
BIP39_VERSION=1.0.4
CORE_LIBRARY_DESUGARING_VERSION=2.0.2
COROUTINES_OKHTTP=1.0
GOOGLE_MATERIAL_VERSION=1.7.0
GRPC_KOTLIN_VERSION=1.3.0

View File

@ -102,12 +102,9 @@ android {
buildTypes {
getByName("debug").apply {
// test builds exceed the dex limit because they pull in large test libraries
multiDexEnabled = true
isMinifyEnabled = false
}
getByName("release").apply {
multiDexEnabled = false
isMinifyEnabled = project.property("IS_MINIFY_SDK_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(

View File

@ -0,0 +1,211 @@
import java.util.Base64
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("zcash-sdk.android-conventions")
id("org.jetbrains.dokka")
id("wtf.emulator.gradle")
id("zcash-sdk.emulator-wtf-conventions")
id("maven-publish")
id("signing")
}
// Publishing information
val publicationVariant = "release"
val myVersion = project.property("LIBRARY_VERSION").toString()
val myArtifactId = "zcash-android-sdk-incubator"
val isSnapshot = project.property("IS_SNAPSHOT").toString().toBoolean()
val version = project.property("LIBRARY_VERSION").toString()
project.group = "cash.z.ecc.android"
publishing {
publications {
register<MavenPublication>("release") {
artifactId = myArtifactId
groupId = "cash.z.ecc.android"
version = if (isSnapshot) {
"$myVersion-SNAPSHOT"
} else {
myVersion
}
afterEvaluate {
from(components[publicationVariant])
}
pom {
name.set("Zcash Android Wallet SDK In")
description.set("This lightweight SDK connects Android to Zcash, allowing third-party " +
"Android apps to send and receive shielded transactions easily, securely and privately.")
url.set("https://github.com/zcash/zcash-android-wallet-sdk/")
inceptionYear.set("2018")
scm {
url.set("https://github.com/zcash/zcash-android-wallet-sdk/")
connection.set("scm:git:git://github.com/zcash/zcash-android-wallet-sdk.git")
developerConnection.set("scm:git:ssh://git@github.com/zcash/zcash-android-wallet-sdk.git")
}
developers {
developer {
id.set("zcash")
name.set("Zcash")
url.set("https://github.com/zcash/")
}
}
licenses {
license {
name.set("The MIT License")
url.set("http://opensource.org/licenses/MIT")
distribution.set("repo")
}
}
}
}
}
repositories {
val mavenUrl = if (isSnapshot) {
project.property("ZCASH_MAVEN_PUBLISH_SNAPSHOT_URL").toString()
} else {
project.property("ZCASH_MAVEN_PUBLISH_RELEASE_URL").toString()
}
val mavenPublishUsername = project.property("ZCASH_MAVEN_PUBLISH_USERNAME").toString()
val mavenPublishPassword = project.property("ZCASH_MAVEN_PUBLISH_PASSWORD").toString()
mavenLocal {
name = "MavenLocal"
}
maven(mavenUrl) {
name = "MavenCentral"
credentials {
username = mavenPublishUsername
password = mavenPublishPassword
}
}
}
}
signing {
// Maven Central requires signing for non-snapshots
isRequired = !isSnapshot
val signingKey = run {
val base64EncodedKey = project.property("ZCASH_ASCII_GPG_KEY").toString()
if (base64EncodedKey.isNotEmpty()) {
val keyBytes = Base64.getDecoder().decode(base64EncodedKey)
String(keyBytes)
} else {
""
}
}
if (signingKey.isNotEmpty()) {
useInMemoryPgpKeys(signingKey, "")
}
sign(publishing.publications)
}
android {
namespace = "cash.z.ecc.android.sdk.incubator"
useLibrary("android.test.runner")
defaultConfig {
consumerProguardFiles("proguard-consumer.txt")
}
buildTypes {
getByName("debug").apply {
isMinifyEnabled = false
}
getByName("release").apply {
isMinifyEnabled = project.property("IS_MINIFY_SDK_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(
getDefaultProguardFile("proguard-android-optimize.txt"),
File("proguard-project.txt")
)
)
}
create("benchmark") {
// We provide the extra benchmark build type just for benchmarking purposes
initWith(buildTypes.getByName("release"))
matchingFallbacks += listOf("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")
}
publishing {
singleVariant(publicationVariant) {
withSourcesJar()
withJavadocJar()
}
}
}
tasks.dokkaHtml.configure {
dokkaSourceSets {
configureEach {
outputDirectory.set(file("build/docs/rtd"))
displayName.set("Zcash Android SDK")
includes.from("packages.md")
}
}
}
dependencies {
implementation(projects.sdkLib)
implementation(libs.bip39)
implementation(libs.androidx.annotation)
implementation(libs.androidx.appcompat)
implementation(libs.kotlinx.datetime)
// Architecture Components: Lifecycle
// implementation(libs.androidx.lifecycle.runtime)
// implementation(libs.androidx.lifecycle.common)
// Kotlin
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
// Tests
testImplementation(libs.kotlin.reflect)
testImplementation(libs.kotlin.test)
testImplementation(libs.bundles.junit)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.kotlin.test)
androidTestImplementation(libs.kotlinx.coroutines.test)
// sample mnemonic plugin
androidTestImplementation(libs.zcashwalletplgn)
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

View File

@ -0,0 +1,19 @@
# This improves obfuscation and moves non-public classes to their own namespace.
# Repackaging into incubator ensures no conflicts with other modules
-repackageclasses 'cash.z.ecc.android.sdk.incubator.internal'
# This makes it easier to autocomplete methods in an IDE using this obfuscated library.
-keepparameternames
# The ProGuard manual recommends keeping these attributes for libraries.
-keepattributes EnclosingMethod,InnerClasses,Signature,Exceptions,*Annotation*
# Ensure that stacktraces are reversible.
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
# Keep the public interface of the library.
# Some of these will need to be tuned in the future, as they shouldn't ALL be considered part of the
# public API. Much of this will be improved by further repackaging of the classes.
-keep public class cash.z.ecc.android.sdk.* { public protected *; }
-keep public class cash.z.ecc.android.sdk.model.* { public protected *; }

View File

@ -0,0 +1,14 @@
package cash.z.ecc.android.sdk
import android.content.Context
import android.text.TextUtils
import android.view.View
import androidx.annotation.StringRes
import androidx.test.core.app.ApplicationProvider
import java.util.Locale
fun getStringResource(@StringRes resId: Int) = ApplicationProvider.getApplicationContext<Context>().getString(resId)
fun getStringResourceWithArgs(@StringRes resId: Int, formatArgs: Array<Any>) = ApplicationProvider.getApplicationContext<Context>().getString(resId, *formatArgs)
fun isLocaleRTL(locale: Locale) = TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL

View File

@ -1,6 +1,6 @@
@file:Suppress("ktlint:filename")
package cash.z.wallet.sdk.sample.demoapp
package cash.z.ecc.android.sdk
fun <T> Iterator<T>.count(): Int {
var count = 0

View File

@ -1,7 +1,7 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.CurrencyConversion
import cash.z.ecc.android.sdk.demoapp.model.FiatCurrency
import cash.z.ecc.android.sdk.model.CurrencyConversion
import cash.z.ecc.android.sdk.model.FiatCurrency
import kotlinx.datetime.Instant
import kotlinx.datetime.toInstant

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.FiatCurrency
import cash.z.ecc.android.sdk.model.FiatCurrency
object FiatCurrencyFixture {
const val USD = "USD"

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.Locale
import cash.z.ecc.android.sdk.model.Locale
object LocaleFixture {
const val LANGUAGE = "en"

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.Memo
import cash.z.ecc.android.sdk.model.Memo
object MemoFixture {
const val MEMO_STRING = "Thanks for lunch"

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.MonetarySeparators
import cash.z.ecc.android.sdk.model.MonetarySeparators
object MonetarySeparatorsFixture {
const val US_GROUPING_SEPARATOR = ','

View File

@ -1,8 +1,8 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.demoapp.model.SeedPhrase
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.PersistableWallet
import cash.z.ecc.android.sdk.model.SeedPhrase
import cash.z.ecc.android.sdk.model.ZcashNetwork
object PersistableWalletFixture {

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.SeedPhrase
import cash.z.ecc.android.sdk.model.SeedPhrase
object SeedPhraseFixture {
@Suppress("MaxLineLength")

View File

@ -1,4 +1,4 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.model.Zatoshi

View File

@ -1,10 +1,9 @@
package cash.z.wallet.sdk.sample.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.fixture.WalletAddressFixture
import cash.z.ecc.android.sdk.demoapp.model.Memo
import cash.z.ecc.android.sdk.demoapp.model.WalletAddress
import cash.z.ecc.android.sdk.demoapp.model.ZecSend
import cash.z.ecc.android.sdk.model.Memo
import cash.z.ecc.android.sdk.model.WalletAddress
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZecSend
object ZecSendFixture {
const val ADDRESS: String = WalletAddressFixture.UNIFIED_ADDRESS_STRING

View File

@ -1,6 +1,5 @@
package cash.z.wallet.sdk.sample.demoapp.ext
package cash.z.ecc.android.sdk.internal
import cash.z.ecc.android.sdk.demoapp.ext.sizeInUtf8Bytes
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -1,12 +1,10 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.ext.ui.toFiatCurrencyState
import cash.z.ecc.android.sdk.demoapp.model.FiatCurrencyConversionRateState
import cash.z.wallet.sdk.sample.demoapp.fixture.CurrencyConversionFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.LocaleFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.MonetarySeparatorsFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.ZatoshiFixture
import cash.z.ecc.android.sdk.fixture.CurrencyConversionFixture
import cash.z.ecc.android.sdk.fixture.LocaleFixture
import cash.z.ecc.android.sdk.fixture.MonetarySeparatorsFixture
import cash.z.ecc.android.sdk.fixture.ZatoshiFixture
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import org.junit.Test

View File

@ -1,9 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.model.Locale
import cash.z.ecc.android.sdk.demoapp.model.toJavaLocale
import cash.z.ecc.android.sdk.demoapp.model.toKotlinLocale
import org.junit.Test
import kotlin.test.assertEquals

View File

@ -1,7 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.sdk.demoapp.model.Memo
import cash.z.wallet.sdk.sample.demoapp.fixture.ZecSendFixture
import cash.z.ecc.android.sdk.fixture.ZecSendFixture
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue

View File

@ -1,7 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.model.PercentDecimal
import org.junit.Test
class PercentDecimalTest {

View File

@ -1,11 +1,9 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.wallet.sdk.sample.demoapp.count
import cash.z.wallet.sdk.sample.demoapp.fixture.PersistableWalletFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.SeedPhraseFixture
import cash.z.ecc.android.sdk.count
import cash.z.ecc.android.sdk.fixture.PersistableWalletFixture
import cash.z.ecc.android.sdk.fixture.SeedPhraseFixture
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue

View File

@ -1,8 +1,7 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.model.SeedPhrase
import cash.z.wallet.sdk.sample.demoapp.fixture.SeedPhraseFixture
import cash.z.ecc.android.sdk.fixture.SeedPhraseFixture
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Test

View File

@ -1,6 +1,6 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.wallet.sdk.sample.demoapp.fixture.WalletAddressFixture
import cash.z.ecc.android.sdk.fixture.WalletAddressFixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlin.test.Test

View File

@ -1,7 +1,7 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.wallet.sdk.sample.demoapp.fixture.WalletAddressesFixture
import cash.z.ecc.android.sdk.fixture.WalletAddressesFixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertFalse

View File

@ -1,12 +1,10 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.ext.ui.toFiatString
import cash.z.ecc.android.sdk.demoapp.model.MonetarySeparators
import cash.z.wallet.sdk.sample.demoapp.fixture.CurrencyConversionFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.LocaleFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.MonetarySeparatorsFixture
import cash.z.wallet.sdk.sample.demoapp.fixture.ZatoshiFixture
import cash.z.ecc.android.sdk.fixture.CurrencyConversionFixture
import cash.z.ecc.android.sdk.fixture.LocaleFixture
import cash.z.ecc.android.sdk.fixture.MonetarySeparatorsFixture
import cash.z.ecc.android.sdk.fixture.ZatoshiFixture
import org.junit.Test
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

View File

@ -1,10 +1,9 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.demoapp.model.ZecStringExt
import cash.z.wallet.sdk.sample.demoapp.fixture.MonetarySeparatorsFixture
import cash.z.wallet.sdk.sample.demoapp.ui.common.getStringResourceWithArgs
import cash.z.ecc.android.sdk.fixture.MonetarySeparatorsFixture
import cash.z.ecc.android.sdk.getStringResourceWithArgs
import cash.z.ecc.android.sdk.incubator.R
import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull

View File

@ -1,13 +1,10 @@
package cash.z.wallet.sdk.sample.demoapp.model
package cash.z.ecc.android.sdk.model
import android.content.Context
import android.content.res.Configuration
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.demoapp.model.fromZecString
import cash.z.ecc.android.sdk.demoapp.model.toZecString
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.wallet.sdk.sample.demoapp.fixture.MonetarySeparatorsFixture
import cash.z.ecc.android.sdk.fixture.MonetarySeparatorsFixture
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application/>
</manifest>

View File

@ -1,12 +1,9 @@
package cash.z.ecc.android.sdk.demoapp
package cash.z.ecc.android.sdk
import android.content.Context
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.demoapp.model.PersistableWallet
import cash.z.ecc.android.sdk.demoapp.util.Twig
import cash.z.ecc.android.sdk.demoapp.util.fromResources
import cash.z.ecc.android.sdk.ext.onFirst
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.internal.Twig2
import cash.z.ecc.android.sdk.model.PersistableWallet
import cash.z.ecc.android.sdk.model.defaultForNetwork
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
import kotlinx.coroutines.CoroutineScope
@ -23,6 +20,7 @@ import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@ -36,7 +34,17 @@ import java.util.UUID
/**
* @param persistableWallet flow of the user's stored wallet. Null indicates that no wallet has been stored.
*/
class WalletCoordinator(context: Context, val persistableWallet: Flow<PersistableWallet?>) {
/*
* One area where this class needs to change before it can be moved out of the incubator is that we need to be able to
* start synchronization without necessarily decrypting the wallet.
*
* Another area that likely needs change is to alter the persistableWallet flow to support a status of "needs
* authentication."
*/
class WalletCoordinator(
context: Context,
val persistableWallet: Flow<PersistableWallet?>
) {
private val applicationContext = context.applicationContext
@ -77,7 +85,7 @@ class WalletCoordinator(context: Context, val persistableWallet: Flow<Persistabl
trySend(InternalSynchronizerStatus.Available(closeableSynchronizer))
awaitClose {
Twig.info { "Closing flow and stopping synchronizer" }
Twig2.info { "Closing flow and stopping synchronizer" }
closeableSynchronizer.close()
}
}
@ -136,25 +144,28 @@ class WalletCoordinator(context: Context, val persistableWallet: Flow<Persistabl
@OptIn(FlowPreview::class)
fun resetSdk() {
walletScope.launch {
lockoutMutex.withLock {
val lockoutId = UUID.randomUUID()
synchronizerLockoutId.value = lockoutId
val zcashNetwork = persistableWallet.first()?.network
if (null != zcashNetwork) {
lockoutMutex.withLock {
val lockoutId = UUID.randomUUID()
synchronizerLockoutId.value = lockoutId
synchronizerOrLockoutId
.flatMapConcat { it }
.filterIsInstance<InternalSynchronizerStatus.Lockout>()
.filter { it.id == lockoutId }
.onFirst {
synchronizerMutex.withLock {
val didDelete = Synchronizer.erase(
appContext = applicationContext,
network = ZcashNetwork.fromResources(applicationContext)
)
Twig.info { "SDK erase result: $didDelete" }
synchronizerOrLockoutId
.flatMapConcat { it }
.filterIsInstance<InternalSynchronizerStatus.Lockout>()
.filter { it.id == lockoutId }
.onFirst {
synchronizerMutex.withLock {
val didDelete = Synchronizer.erase(
appContext = applicationContext,
network = zcashNetwork
)
Twig2.info { "SDK erase result: $didDelete" }
}
}
}
synchronizerLockoutId.value = null
synchronizerLockoutId.value = null
}
}
}
}

View File

@ -1,6 +1,6 @@
package cash.z.ecc.android.sdk.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.WalletAddress
import cash.z.ecc.android.sdk.model.WalletAddress
object WalletAddressFixture {
// These fixture values are derived from the secret defined in PersistableWalletFixture

View File

@ -1,7 +1,7 @@
package cash.z.ecc.android.sdk.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.sdk.demoapp.model.WalletAddress
import cash.z.ecc.android.sdk.demoapp.model.WalletAddresses
import cash.z.ecc.android.sdk.model.WalletAddress
import cash.z.ecc.android.sdk.model.WalletAddresses
object WalletAddressesFixture {

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.fixture
package cash.z.ecc.android.sdk.fixture
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.sdk.model.Account

View File

@ -1,6 +1,6 @@
@file:Suppress("ktlint:filename")
package cash.z.ecc.android.sdk.demoapp.ext
package cash.z.ecc.android.sdk.internal
import java.nio.charset.Charset

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.util
package cash.z.ecc.android.sdk.internal
import android.app.ActivityManager
import android.app.Application
@ -15,7 +15,7 @@ import java.util.Locale
* or usage in production.
*/
@Suppress("TooManyFunctions")
object Twig {
object Twig2 {
/**
* Format string for log messages.
*
@ -157,13 +157,18 @@ private fun cleanupClassName(classNameString: String): String {
* due to some race conditions in Android.
*/
private fun searchForProcessName(context: Context): String? {
return if (AndroidApiVersion.isAtLeastP) {
return if (AndroidApiVersion.isAtLeastT) {
getProcessNameTPlus()
} else if (AndroidApiVersion.isAtLeastP) {
getProcessNamePPlus()
} else {
searchForProcessNameLegacy(context)
}
}
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private fun getProcessNameTPlus() = Process.myProcessName()
@RequiresApi(api = Build.VERSION_CODES.P)
private fun getProcessNamePPlus() = Application.getProcessName()

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import kotlinx.datetime.Instant

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.minutes

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
data class Locale(val language: String, val region: String?, val variant: String?) {
companion object

View File

@ -1,6 +1,6 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.sdk.demoapp.ext.sizeInUtf8Bytes
import cash.z.ecc.android.sdk.internal.sizeInUtf8Bytes
@JvmInline
value class Memo(val value: String) {

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
/**
* @param decimal A percent represented as a `Double` decimal value in the range of [0, 1].

View File

@ -1,11 +1,8 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import android.app.Application
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toEntropy
import cash.z.ecc.android.sdk.demoapp.util.fromResources
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.ZcashNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONObject
@ -70,8 +67,7 @@ data class PersistableWallet(
/**
* @return A new PersistableWallet with a random seed phrase.
*/
suspend fun new(application: Application): PersistableWallet {
val zcashNetwork = ZcashNetwork.fromResources(application)
suspend fun new(application: Application, zcashNetwork: ZcashNetwork): PersistableWallet {
val birthday = BlockHeight.ofLatestCheckpoint(application, zcashNetwork)
val seedPhrase = newSeedPhrase()

View File

@ -1,4 +1,4 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed

View File

@ -1,12 +1,12 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
sealed class WalletAddress(val address: String) {
class Unified private constructor(address: String) : WalletAddress(address) {
companion object {
suspend fun new(address: String): WalletAddress.Unified {
suspend fun new(address: String): Unified {
// https://github.com/zcash/zcash-android-wallet-sdk/issues/342
// TODO [#342]: refactor SDK to enable direct calls for address verification
return WalletAddress.Unified(address)
return Unified(address)
}
}
}

View File

@ -1,7 +1,6 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.Account
data class WalletAddresses(
val unified: WalletAddress.Unified,

View File

@ -1,14 +1,8 @@
@file:Suppress("ktlint:filename")
package cash.z.ecc.android.sdk.demoapp.ext.ui
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.sdk.demoapp.model.CurrencyConversion
import cash.z.ecc.android.sdk.demoapp.model.FiatCurrencyConversionRateState
import cash.z.ecc.android.sdk.demoapp.model.Locale
import cash.z.ecc.android.sdk.demoapp.model.MonetarySeparators
import cash.z.ecc.android.sdk.demoapp.model.toJavaLocale
import cash.z.ecc.android.sdk.ext.Conversions
import cash.z.ecc.android.sdk.model.Zatoshi
import kotlinx.datetime.Clock
import java.math.BigDecimal
import java.math.MathContext

View File

@ -1,8 +1,6 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
import cash.z.ecc.android.sdk.model.Zatoshi
data class ZecSend(val destination: WalletAddress, val amount: Zatoshi, val memo: Memo) {
companion object

View File

@ -1,7 +1,6 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import android.content.Context
import cash.z.ecc.android.sdk.model.Zatoshi
import kotlinx.coroutines.runBlocking
object ZecSendExt {

View File

@ -1,9 +1,8 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import android.content.Context
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
import cash.z.ecc.android.sdk.ext.convertZecToZatoshi
import cash.z.ecc.android.sdk.model.Zatoshi
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat

View File

@ -1,7 +1,7 @@
package cash.z.ecc.android.sdk.demoapp.model
package cash.z.ecc.android.sdk.model
import android.content.Context
import cash.z.ecc.android.sdk.demoapp.R
import cash.z.ecc.android.sdk.incubator.R
object ZecStringExt {

View File

@ -128,11 +128,9 @@ android {
buildTypes {
getByName("debug").apply {
// test builds exceed the dex limit because they pull in large test libraries
multiDexEnabled = true
isMinifyEnabled = false
}
getByName("release").apply {
multiDexEnabled = false
isMinifyEnabled = project.property("IS_MINIFY_SDK_ENABLED").toString().toBoolean()
proguardFiles.addAll(
listOf(

View File

@ -267,4 +267,5 @@ include("darkside-test-lib")
include("demo-app")
include("demo-app-benchmark-test")
include("lightwallet-client-lib")
include("sdk-incubator-lib")
include("sdk-lib")