Merge + changelog update

- Updated changelog
- Merged branch 'main' into 615-networking-module

* main:
  [#882] Check properties on CI
  [#874] GRPC 1.52.1
  [#892] Emulator.wtf Gradle Plugin 0.0.15
  [#888] Android Gradle Plugin 7.4
  [#851] Androidx Updates
  [#851] Kotlin 1.8
  [#779] Resolve flaky DatabaseCoordinatorTest
  [#886] Support null block heights
  [#881] Use variables for Test Lab
  [#860] Flank 23.01.0

# Conflicts:
#	CHANGELOG.md
#	gradle.properties
This commit is contained in:
Honza 2023-01-30 09:56:21 +01:00
commit 0e4d634693
23 changed files with 272 additions and 225 deletions

View File

@ -87,7 +87,7 @@ jobs:
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
timeout-minutes: 2 timeout-minutes: 3
with: with:
name: Release binaries name: Release binaries
path: ~/artifacts path: ~/artifacts

View File

@ -94,7 +94,7 @@ jobs:
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
timeout-minutes: 2 timeout-minutes: 3
with: with:
name: Snapshot binaries name: Snapshot binaries
path: ~/artifacts path: ~/artifacts

View File

@ -1,9 +1,11 @@
# Expected secrets # Expected secrets
# EMULATOR_WTF_API_KEY - Optional API key for emulator.wtf # EMULATOR_WTF_API_KEY - Optional API key for emulator.wtf
# FIREBASE_TEST_LAB_PROJECT - Firebase Test Lab project name
# FIREBASE_TEST_LAB_SERVICE_ACCOUNT - Email address of Firebase Test Lab service account # FIREBASE_TEST_LAB_SERVICE_ACCOUNT - Email address of Firebase Test Lab service account
# FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER - Workload identity provider to generate temporary service account key # FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER - Workload identity provider to generate temporary service account key
# Expected variables
# FIREBASE_TEST_LAB_PROJECT - Firebase Test Lab project name
name: Pull Request name: Pull Request
on: on:
@ -45,7 +47,7 @@ jobs:
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 35
uses: ./.github/actions/setup uses: ./.github/actions/setup
check_firebase_secrets: check_firebase_secrets:
@ -55,7 +57,7 @@ jobs:
steps: steps:
- id: check_firebase_secrets - id: check_firebase_secrets
env: env:
FIREBASE_TEST_LAB_PROJECT: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }} FIREBASE_TEST_LAB_PROJECT: ${{ vars.FIREBASE_TEST_LAB_PROJECT }}
FIREBASE_TEST_LAB_SERVICE_ACCOUNT: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }} FIREBASE_TEST_LAB_SERVICE_ACCOUNT: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }}
FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }} FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }}
if: "${{ env.FIREBASE_TEST_LAB_PROJECT != '' && env.FIREBASE_TEST_LAB_SERVICE_ACCOUNT != '' && env.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER != '' }}" if: "${{ env.FIREBASE_TEST_LAB_PROJECT != '' && env.FIREBASE_TEST_LAB_SERVICE_ACCOUNT != '' && env.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER != '' }}"
@ -72,6 +74,24 @@ jobs:
if: "${{ env.EMULATOR_WTF_API_KEY != '' }}" if: "${{ env.EMULATOR_WTF_API_KEY != '' }}"
run: echo "defined=true" >> $GITHUB_OUTPUT run: echo "defined=true" >> $GITHUB_OUTPUT
check_properties:
needs: prime_cache
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
timeout-minutes: 1
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
- name: Setup
id: setup
timeout-minutes: 5
uses: ./.github/actions/setup
- name: Check properties
timeout-minutes: 4
run: |
./gradlew checkProperties
static_analysis_detekt: static_analysis_detekt:
needs: prime_cache needs: prime_cache
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -239,7 +259,7 @@ jobs:
uses: google-github-actions/auth@ef5d53e30bbcd8d0836f4288f5e50ff3e086997d uses: google-github-actions/auth@ef5d53e30bbcd8d0836f4288f5e50ff3e086997d
with: with:
create_credentials_file: true create_credentials_file: true
project_id: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }} project_id: ${{ vars.FIREBASE_TEST_LAB_PROJECT }}
service_account: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }} service_account: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }}
workload_identity_provider: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }} workload_identity_provider: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }}
access_token_lifetime: '1200s' access_token_lifetime: '1200s'
@ -247,7 +267,7 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
env: env:
# This first environment variable is used by Flank, since the temporary token is missing the project name # This first environment variable is used by Flank, since the temporary token is missing the project name
GOOGLE_CLOUD_PROJECT: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }} GOOGLE_CLOUD_PROJECT: ${{ vars.FIREBASE_TEST_LAB_PROJECT }}
ORG_GRADLE_PROJECT_ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH: ${{ steps.auth_test_lab.outputs.credentials_file_path }} ORG_GRADLE_PROJECT_ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH: ${{ steps.auth_test_lab.outputs.credentials_file_path }}
# Because Fulladle doesn't allow Test Orchestrator to be enabled/disabled for a specific submodule, it must be enabled for all modules # Because Fulladle doesn't allow Test Orchestrator to be enabled/disabled for a specific submodule, it must be enabled for all modules
ORG_GRADLE_PROJECT_IS_USE_TEST_ORCHESTRATOR: true ORG_GRADLE_PROJECT_IS_USE_TEST_ORCHESTRATOR: true
@ -377,7 +397,7 @@ jobs:
uses: google-github-actions/auth@ef5d53e30bbcd8d0836f4288f5e50ff3e086997d uses: google-github-actions/auth@ef5d53e30bbcd8d0836f4288f5e50ff3e086997d
with: with:
create_credentials_file: true create_credentials_file: true
project_id: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }} project_id: ${{ vars.FIREBASE_TEST_LAB_PROJECT }}
service_account: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }} service_account: ${{ secrets.FIREBASE_TEST_LAB_SERVICE_ACCOUNT }}
workload_identity_provider: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }} workload_identity_provider: ${{ secrets.FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER }}
access_token_lifetime: '900s' access_token_lifetime: '900s'
@ -391,7 +411,7 @@ jobs:
# Path depends on `release_build` job, plus path of `Download a single artifact` step # Path depends on `release_build` job, plus path of `Download a single artifact` step
BINARIES_ZIP_PATH: binaries.zip BINARIES_ZIP_PATH: binaries.zip
# This first environment variable is used by Flank, since the temporary token is missing the project name # This first environment variable is used by Flank, since the temporary token is missing the project name
GOOGLE_CLOUD_PROJECT: ${{ secrets.FIREBASE_TEST_LAB_PROJECT }} GOOGLE_CLOUD_PROJECT: ${{ vars.FIREBASE_TEST_LAB_PROJECT }}
ORG_GRADLE_PROJECT_ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH: ${{ steps.auth_test_lab.outputs.credentials_file_path }} ORG_GRADLE_PROJECT_ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH: ${{ steps.auth_test_lab.outputs.credentials_file_path }}
run: | run: |
unzip ${BINARIES_ZIP_PATH} unzip ${BINARIES_ZIP_PATH}

View File

@ -3,12 +3,19 @@ Change Log
Unreleased Unreleased
------------------------------------ ------------------------------------
- The SDK's internal networking has been refactored to a separate Gradle module (and therefore a separate artifact) which is a transitive dependency of the Zcash Android SDK. - The SDK's internal networking has been refactored to a separate Gradle module `lightwallet-client-lib` (and
therefore a separate artifact) which is a transitive dependency of the Zcash Android SDK.
- The `z.cash.ecc.android.sdk.model.LightWalletEndpoint` class has been moved to `co.electriccoin.lightwallet.client.model.LightWalletEndpoint` - The `z.cash.ecc.android.sdk.model.LightWalletEndpoint` class has been moved to `co.electriccoin.lightwallet.client.model.LightWalletEndpoint`
- The new networking module now provides a `BlockingLightWalletClient` for blocking calls and a
`CoroutineLightWalletClient` for asynchronous calls.
- Most unary calls respond with the new `Response` class and its subclasses. Streaming calls will be updated
with the Response class later.
Unreleased ## 1.12.0-beta01
------------------------------------ ### Changed
- `TransactionOverview`, `Transaction.Sent`, and `Transaction.Received` have `minedHeight` as a nullable field now. This fixes a potential crash when fetching transactions when a transaction is in the mempool
## 1.11.0-beta01
### Added ### Added
- `cash.z.ecc.android.sdk`: - `cash.z.ecc.android.sdk`:
- `Synchronizer.getUnifiedAddress` - `Synchronizer.getUnifiedAddress`

View File

@ -36,12 +36,9 @@ dependencyLocking {
} }
} }
// Per conversation in the KotlinLang Slack, Gradle uses Java 8 compatibility internally
// for all build scripts.
// https://kotlinlang.slack.com/archives/C19FD9681/p1636632870122900?thread_ts=1636572288.117000&cid=C19FD9681
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_11
} }
dependencies { dependencies {

View File

@ -1,50 +1,51 @@
# This is a Gradle generated file for dependency locking. # This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised. # Manual edits can break the build and are not advised.
# This file is expected to be part of source control. # This file is expected to be part of source control.
androidx.databinding:databinding-common:7.3.0=runtimeClasspath androidx.databinding:databinding-common:7.4.0=runtimeClasspath
androidx.databinding:databinding-compiler-common:7.3.0=runtimeClasspath androidx.databinding:databinding-compiler-common:7.4.0=runtimeClasspath
com.android.databinding:baseLibrary:7.3.0=runtimeClasspath com.android.databinding:baseLibrary:7.4.0=runtimeClasspath
com.android.tools.analytics-library:crash:30.3.0=runtimeClasspath com.android.tools.analytics-library:crash:30.4.0=runtimeClasspath
com.android.tools.analytics-library:protos:30.3.0=runtimeClasspath com.android.tools.analytics-library:protos:30.4.0=runtimeClasspath
com.android.tools.analytics-library:shared:30.3.0=runtimeClasspath com.android.tools.analytics-library:shared:30.4.0=runtimeClasspath
com.android.tools.analytics-library:tracker:30.3.0=runtimeClasspath com.android.tools.analytics-library:tracker:30.4.0=runtimeClasspath
com.android.tools.build.jetifier:jetifier-core:1.0.0-beta10=runtimeClasspath com.android.tools.build.jetifier:jetifier-core:1.0.0-beta10=runtimeClasspath
com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta10=runtimeClasspath com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta10=runtimeClasspath
com.android.tools.build:aapt2-proto:7.3.0-8691043=runtimeClasspath com.android.tools.build:aapt2-proto:7.4.0-8841542=runtimeClasspath
com.android.tools.build:aaptcompiler:7.3.0=runtimeClasspath com.android.tools.build:aaptcompiler:7.4.0=runtimeClasspath
com.android.tools.build:apksig:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:apksig:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:apkzlib:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:apkzlib:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:builder-model:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:builder-model:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:builder-test-api:7.3.0=runtimeClasspath com.android.tools.build:builder-test-api:7.4.0=runtimeClasspath
com.android.tools.build:builder:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:builder:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:bundletool:1.9.0=runtimeClasspath com.android.tools.build:bundletool:1.11.4=runtimeClasspath
com.android.tools.build:gradle-api:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:gradle-api:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:gradle:7.3.0=compileClasspath,runtimeClasspath com.android.tools.build:gradle-settings-api:7.4.0=runtimeClasspath
com.android.tools.build:manifest-merger:30.3.0=compileClasspath,runtimeClasspath com.android.tools.build:gradle:7.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:manifest-merger:30.4.0=compileClasspath,runtimeClasspath
com.android.tools.build:transform-api:2.0.0-deprecated-use-gradle-api=runtimeClasspath com.android.tools.build:transform-api:2.0.0-deprecated-use-gradle-api=runtimeClasspath
com.android.tools.ddms:ddmlib:30.3.0=runtimeClasspath com.android.tools.ddms:ddmlib:30.4.0=runtimeClasspath
com.android.tools.layoutlib:layoutlib-api:30.3.0=runtimeClasspath com.android.tools.layoutlib:layoutlib-api:30.4.0=runtimeClasspath
com.android.tools.lint:lint-model:30.3.0=runtimeClasspath com.android.tools.lint:lint-model:30.4.0=runtimeClasspath
com.android.tools.lint:lint-typedef-remover:30.3.0=runtimeClasspath com.android.tools.lint:lint-typedef-remover:30.4.0=runtimeClasspath
com.android.tools.utp:android-device-provider-ddmlib-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-device-provider-ddmlib-proto:30.4.0=runtimeClasspath
com.android.tools.utp:android-device-provider-gradle-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-device-provider-gradle-proto:30.4.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:30.4.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-coverage-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-test-plugin-host-coverage-proto:30.4.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-retention-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-test-plugin-host-retention-proto:30.4.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.3.0=runtimeClasspath com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.4.0=runtimeClasspath
com.android.tools:annotations:30.3.0=runtimeClasspath com.android.tools:annotations:30.4.0=runtimeClasspath
com.android.tools:common:30.3.0=runtimeClasspath com.android.tools:common:30.4.0=runtimeClasspath
com.android.tools:dvlib:30.3.0=runtimeClasspath com.android.tools:dvlib:30.4.0=runtimeClasspath
com.android.tools:repository:30.3.0=runtimeClasspath com.android.tools:repository:30.4.0=runtimeClasspath
com.android.tools:sdk-common:30.3.0=runtimeClasspath com.android.tools:sdk-common:30.4.0=runtimeClasspath
com.android.tools:sdklib:30.3.0=runtimeClasspath com.android.tools:sdklib:30.4.0=runtimeClasspath
com.android:signflinger:7.3.0=runtimeClasspath com.android:signflinger:7.4.0=runtimeClasspath
com.android:zipflinger:7.3.0=compileClasspath,runtimeClasspath com.android:zipflinger:7.4.0=compileClasspath,runtimeClasspath
com.google.android:annotations:4.1.1.4=runtimeClasspath com.google.android:annotations:4.1.1.4=runtimeClasspath
com.google.api.grpc:proto-google-common-protos:2.0.1=runtimeClasspath com.google.api.grpc:proto-google-common-protos:2.0.1=runtimeClasspath
com.google.auto.value:auto-value-annotations:1.6.2=runtimeClasspath com.google.auto.value:auto-value-annotations:1.6.2=runtimeClasspath
com.google.code.findbugs:jsr305:3.0.2=runtimeClasspath com.google.code.findbugs:jsr305:3.0.2=runtimeClasspath
com.google.code.gson:gson:2.8.6=runtimeClasspath com.google.code.gson:gson:2.8.9=runtimeClasspath
com.google.crypto.tink:tink:1.3.0-rc2=runtimeClasspath com.google.crypto.tink:tink:1.3.0-rc2=runtimeClasspath
com.google.dagger:dagger:2.28.3=runtimeClasspath com.google.dagger:dagger:2.28.3=runtimeClasspath
com.google.errorprone:error_prone_annotations:2.4.0=runtimeClasspath com.google.errorprone:error_prone_annotations:2.4.0=runtimeClasspath
@ -56,8 +57,7 @@ com.google.j2objc:j2objc-annotations:1.3=runtimeClasspath
com.google.jimfs:jimfs:1.1=runtimeClasspath com.google.jimfs:jimfs:1.1=runtimeClasspath
com.google.protobuf:protobuf-java-util:3.17.2=runtimeClasspath com.google.protobuf:protobuf-java-util:3.17.2=runtimeClasspath
com.google.protobuf:protobuf-java:3.17.2=runtimeClasspath com.google.protobuf:protobuf-java:3.17.2=runtimeClasspath
com.google.testing.platform:core-proto:0.0.8-alpha07=runtimeClasspath com.google.testing.platform:core-proto:0.0.8-alpha08=runtimeClasspath
com.googlecode.json-simple:json-simple:1.1=runtimeClasspath
com.googlecode.juniversalchardet:juniversalchardet:1.0.3=runtimeClasspath com.googlecode.juniversalchardet:juniversalchardet:1.0.3=runtimeClasspath
com.squareup:javapoet:1.10.0=runtimeClasspath com.squareup:javapoet:1.10.0=runtimeClasspath
com.squareup:javawriter:2.5.0=compileClasspath,runtimeClasspath com.squareup:javawriter:2.5.0=compileClasspath,runtimeClasspath
@ -86,7 +86,6 @@ io.netty:netty-handler:4.1.52.Final=runtimeClasspath
io.netty:netty-resolver:4.1.52.Final=runtimeClasspath io.netty:netty-resolver:4.1.52.Final=runtimeClasspath
io.netty:netty-transport:4.1.52.Final=runtimeClasspath io.netty:netty-transport:4.1.52.Final=runtimeClasspath
io.perfmark:perfmark-api:0.23.0=runtimeClasspath io.perfmark:perfmark-api:0.23.0=runtimeClasspath
it.unimi.dsi:fastutil:8.4.0=runtimeClasspath
jakarta.activation:jakarta.activation-api:1.2.1=runtimeClasspath jakarta.activation:jakarta.activation-api:1.2.1=runtimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:2.3.2=runtimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:2.3.2=runtimeClasspath
javax.annotation:javax.annotation-api:1.3.2=runtimeClasspath javax.annotation:javax.annotation-api:1.3.2=runtimeClasspath
@ -108,64 +107,59 @@ org.glassfish.jaxb:jaxb-runtime:2.3.2=runtimeClasspath
org.glassfish.jaxb:txw2:2.3.2=runtimeClasspath org.glassfish.jaxb:txw2:2.3.2=runtimeClasspath
org.jdom:jdom2:2.0.6=runtimeClasspath org.jdom:jdom2:2.0.6=runtimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,runtimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-android-extensions:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-android-extensions:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-build-common:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-build-common:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-compiler-runner:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-daemon-client:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-daemon-client:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-native-utils:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-native-utils:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-native-utils:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-native-utils:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-project-model:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-project-model:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-project-model:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-project-model:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.5.31=runtimeClasspath org.jetbrains.kotlin:kotlin-reflect:1.7.10=compileClasspath,kotlinCompilerClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=compileClasspath,kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-sam-with-receiver:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-sam-with-receiver:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-common:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-common:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.0=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.5.31=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=compileClasspath org.jetbrains.kotlin:kotlin-stdlib:1.7.10=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=compileClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.5.31=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-tooling-core:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-tooling-core:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-tooling-core:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-tooling-core:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-util-io:1.7.10=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-util-io:1.7.10=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-util-io:1.7.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-util-io:1.8.0=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-util-klib:1.7.21=runtimeClasspath org.jetbrains.kotlin:kotlin-util-klib:1.8.0=runtimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=runtimeClasspath org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=runtimeClasspath
org.jetbrains:annotations:13.0=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,runtimeClasspath org.jetbrains:annotations:13.0=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,runtimeClasspath
org.json:json:20180813=runtimeClasspath org.json:json:20180813=runtimeClasspath
org.jvnet.staxex:stax-ex:1.8.1=runtimeClasspath org.jvnet.staxex:stax-ex:1.8.1=runtimeClasspath
org.ow2.asm:asm-analysis:9.1=runtimeClasspath org.ow2.asm:asm-analysis:9.2=runtimeClasspath
org.ow2.asm:asm-commons:9.1=runtimeClasspath org.ow2.asm:asm-commons:9.2=runtimeClasspath
org.ow2.asm:asm-tree:9.1=runtimeClasspath org.ow2.asm:asm-tree:9.2=runtimeClasspath
org.ow2.asm:asm-util:9.1=runtimeClasspath org.ow2.asm:asm-util:9.2=runtimeClasspath
org.ow2.asm:asm:9.1=compileClasspath,runtimeClasspath org.ow2.asm:asm:9.2=compileClasspath,runtimeClasspath
org.slf4j:slf4j-api:1.7.30=runtimeClasspath org.slf4j:slf4j-api:1.7.30=runtimeClasspath
org.tensorflow:tensorflow-lite-metadata:0.1.0-rc2=runtimeClasspath org.tensorflow:tensorflow-lite-metadata:0.1.0-rc2=runtimeClasspath
wtf.emulator:gradle-plugin:0.0.12=compileClasspath,runtimeClasspath wtf.emulator:gradle-plugin:0.0.15=compileClasspath,runtimeClasspath
xerces:xercesImpl:2.12.0=runtimeClasspath xerces:xercesImpl:2.12.0=runtimeClasspath
xml-apis:xml-apis:1.4.01=runtimeClasspath xml-apis:xml-apis:1.4.01=runtimeClasspath
empty=annotationProcessor,kotlinScriptDefExtensions empty=annotationProcessor,kotlinScriptDefExtensions

View File

@ -31,6 +31,7 @@ pluginManager.withPlugin("com.android.library") {
defaultConfig { defaultConfig {
minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt() minSdk = project.property("ANDROID_MIN_SDK_VERSION").toString().toInt()
// This is deprecated but there isn't a replacement for it yet with instrumentation tests.
targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt() targetSdk = project.property("ANDROID_TARGET_SDK_VERSION").toString().toInt()
// The last two are for support of pseudolocales in debug builds. // The last two are for support of pseudolocales in debug builds.

View File

@ -46,6 +46,48 @@ tasks {
} }
} }
} }
register("checkProperties") {
doLast {
// Ensure that developers do not change default values of certain properties directly in the repo, but
// instead set them in their local ~/.gradle/gradle.properties file (or use command line arguments)
val expectedPropertyValues = mapOf(
"ZCASH_MAVEN_PUBLISH_USERNAME" to "",
"ZCASH_MAVEN_PUBLISH_PASSWORD" to "",
"ZCASH_ASCII_GPG_KEY" to "",
"IS_SNAPSHOT" to "true",
"ZCASH_IS_TREAT_WARNINGS_AS_ERRORS" to "true",
"IS_USE_TEST_ORCHESTRATOR" to "false",
"ZCASH_FIREBASE_TEST_LAB_API_KEY_PATH" to "",
"ZCASH_FIREBASE_TEST_LAB_PROJECT" to "",
"ZCASH_EMULATOR_WTF_API_KEY" to "",
"IS_MINIFY_SDK_ENABLED" to "false",
"IS_MINIFY_APP_ENABLED" to "true",
"ZCASH_DEBUG_KEYSTORE_PATH" to "",
"ZCASH_RELEASE_KEYSTORE_PATH" to "",
"ZCASH_RELEASE_KEYSTORE_PASSWORD" to "",
"ZCASH_RELEASE_KEY_ALIAS" to "",
"ZCASH_RELEASE_KEY_ALIAS_PASSWORD" to "",
"IS_SIGN_RELEASE_BUILD_WITH_DEBUG_KEY" to "false",
)
val warnings = expectedPropertyValues.filter { (key, value) ->
project.properties[key].toString() != value
}.map { "Property ${it.key} does not have expected value \"${it.value}\"" }
if (warnings.isNotEmpty()) {
throw GradleException(warnings.joinToString(separator = "\n"))
}
}
}
} }
val unstableKeywords = listOf("alpha", "beta", "rc", "m", "ea", "build") val unstableKeywords = listOf("alpha", "beta", "rc", "m", "ea", "build")

View File

@ -7,7 +7,6 @@ import androidx.activity.viewModels
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cash.z.ecc.android.sdk.demoapp.ui.common.BindCompLocalProvider import cash.z.ecc.android.sdk.demoapp.ui.common.BindCompLocalProvider
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.SecretState import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.SecretState
@ -33,7 +32,6 @@ class ComposeActivity : ComponentActivity() {
} }
} }
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable @Composable
private fun MainContent() { private fun MainContent() {
when (walletViewModel.secretState.collectAsStateWithLifecycle().value) { when (walletViewModel.secretState.collectAsStateWithLifecycle().value) {

View File

@ -11,7 +11,6 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder import androidx.navigation.NavOptionsBuilder
@ -33,7 +32,6 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable @Composable
@Suppress("LongMethod") @Suppress("LongMethod")
internal fun ComposeActivity.Navigation() { internal fun ComposeActivity.Navigation() {

View File

@ -4,7 +4,9 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import cash.z.ecc.android.bip39.Mnemonics import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed import cash.z.ecc.android.bip39.toSeed
import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
@ -42,22 +44,24 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
private fun displayKeys() { private fun displayKeys() {
// derive the keys from the seed: // derive the keys from the seed:
// demonstrate deriving spending keys for five accounts but only take the first one // demonstrate deriving spending keys for five accounts but only take the first one
lifecycleScope.launchWhenStarted { lifecycleScope.launch {
@Suppress("MagicNumber") viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
val spendingKey = DerivationTool.deriveUnifiedSpendingKey( @Suppress("MagicNumber")
seed, val spendingKey = DerivationTool.deriveUnifiedSpendingKey(
ZcashNetwork.fromResources(requireApplicationContext()), seed,
Account(5) ZcashNetwork.fromResources(requireApplicationContext()),
) Account(5)
)
// derive the key that allows you to view but not spend transactions // derive the key that allows you to view but not spend transactions
val viewingKey = DerivationTool.deriveUnifiedFullViewingKey( val viewingKey = DerivationTool.deriveUnifiedFullViewingKey(
spendingKey, spendingKey,
ZcashNetwork.fromResources(requireApplicationContext()) ZcashNetwork.fromResources(requireApplicationContext())
) )
// display the keys in the UI // display the keys in the UI
binding.textInfo.setText("Spending Key:\n$spendingKey\n\nViewing Key:\n$viewingKey") binding.textInfo.setText("Spending Key:\n$spendingKey\n\nViewing Key:\n$viewingKey")
}
} }
} }
@ -75,8 +79,8 @@ class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
return view return view
} }
override fun onResume() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onResume() super.onViewCreated(view, savedInstanceState)
displayKeys() displayKeys()
} }

View File

@ -5,18 +5,19 @@ Workflows exist for:
* Pull request - On pull request, static analysis and testing is performed. * Pull request - On pull request, static analysis and testing is performed.
* Snapshot deployment - On merge to the main branch, a snapshot release is deployed to Maven Central. Concurrency limits are in place, to ensure that only one snapshot deployment can happen at a time. * Snapshot deployment - On merge to the main branch, a snapshot release is deployed to Maven Central. Concurrency limits are in place, to ensure that only one snapshot deployment can happen at a time.
* Release deployment - Manually invoked workflow to deploy to Maven Central. Concurrency limits are in place, to ensure that only one release deployment can happen at a time. * Release deployment - Manually invoked workflow to deploy to Maven Central. Concurrency limits are in place, to ensure that only one release deployment can happen at a time.
* Unwedge — If Snapshot deployment fails, it will often be due to multiple unclosed repositories. This workflow can take a given open repository name and attempt to close it.
## Setup ## Setup
When forking this repository, some secrets need to be defined to set up new continuous integration builds. When forking this repository, some vars/secrets need to be defined to set up new continuous integration builds.
The secrets passed to GitHub Actions then map to Gradle properties set up within our build scripts. Necessary secrets are documented at the top of each GitHub workflow yml file, as well as reiterated here. The vars/secrets passed to GitHub Actions then map to Gradle properties set up within our build scripts. Necessary secrets are documented at the top of each GitHub workflow yml file, as well as reiterated here.
### Pull request ### Pull request
* `EMULATOR_WTF_API_KEY` - API key for [Emulator.wtf](https://emulator.wtf) * Variables
* `FIREBASE_TEST_LAB_PROJECT` - Firebase Test Lab project name. * `FIREBASE_TEST_LAB_PROJECT` - Firebase Test Lab project name.
* `FIREBASE_TEST_LAB_SERVICE_ACCOUNT` - Email address of Firebase Test Lab service account. * Secrets
* `FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER` - Workload identity provider to generate temporary service account key. * `EMULATOR_WTF_API_KEY` - API key for [Emulator.wtf](https://emulator.wtf)
* `FIREBASE_TEST_LAB_SERVICE_ACCOUNT` - Email address of Firebase Test Lab service account.
* `FIREBASE_TEST_LAB_WORKLOAD_IDENTITY_PROVIDER` - Workload identity provider to generate temporary service account key.
The Pull Request workflow supports testing of the app and libraries with both Emulator.wtf and Firebase Test Lab. By default Emulator.wtf is used for library instrumentation tests, while Firebase Test Lab is used for a robo test. The Pull Request workflow supports testing of the app and libraries with both Emulator.wtf and Firebase Test Lab. By default Emulator.wtf is used for library instrumentation tests, while Firebase Test Lab is used for a robo test.
@ -27,8 +28,9 @@ To configure Firebase Test Lab, you'll need to enable the necessary Google Cloud
Note: Pull requests do not currently run darkside tests. See #361. Note: Pull requests do not currently run darkside tests. See #361.
### Snapshot deployment ### Snapshot deployment
* `MAVEN_CENTRAL_USERNAME` — Username for Maven Central, which maps to the Gradle property `mavenCentralUsername`. * Secrets
* `MAVEN_CENTRAL_PASSWORD` — Password for Maven Central, which maps to the Gradle property `mavenCentralPassword`. * `MAVEN_CENTRAL_USERNAME` — Username for Maven Central, which maps to the Gradle property `mavenCentralUsername`.
* `MAVEN_CENTRAL_PASSWORD` — Password for Maven Central, which maps to the Gradle property `mavenCentralPassword`.
GPG keys are not needed for snapshot deployment. GPG keys are not needed for snapshot deployment.
@ -37,16 +39,13 @@ Note: For documentation on the Gradle properties for Maven deployment, see [Grad
Note: Snapshot builds are configured with a Gradle property `IS_SNAPSHOT`. The workflow automatically sets this property to true for snapshot deployments. This will suffix the version with `-SNAPSHOT` and will upload to the snapshot repository. Note: Snapshot builds are configured with a Gradle property `IS_SNAPSHOT`. The workflow automatically sets this property to true for snapshot deployments. This will suffix the version with `-SNAPSHOT` and will upload to the snapshot repository.
### Release deployment ### Release deployment
* `MAVEN_CENTRAL_USERNAME` — Username for Maven Central, which maps to the Gradle property `mavenCentralUsername`. * Secrets
* `MAVEN_CENTRAL_PASSWORD` — Password for Maven Central, which maps to the Gradle property `mavenCentralPassword`. * `MAVEN_CENTRAL_USERNAME` — Username for Maven Central, which maps to the Gradle property `mavenCentralUsername`.
* `MAVEN_SIGNING_KEYRING_FILE_BASE64` — GPG keyring file, base64 encoded. Maps to Gradle property `signing.secretKeyRingFile`. * `MAVEN_CENTRAL_PASSWORD` — Password for Maven Central, which maps to the Gradle property `mavenCentralPassword`.
* `MAVEN_SIGNING_KEY_ID` — Name of key inside GPG keyring file. Maps to Gradle property `signing.keyId`. * `MAVEN_SIGNING_KEYRING_FILE_BASE64` — GPG keyring file, base64 encoded. Maps to Gradle property `signing.secretKeyRingFile`.
* `MAVEN_SIGNING_PASSWORD` — Password for key inside GPG keyring file. Maps to Gradle property `signing.password`. * `MAVEN_SIGNING_KEY_ID` — Name of key inside GPG keyring file. Maps to Gradle property `signing.keyId`.
* `MAVEN_SIGNING_PASSWORD` — Password for key inside GPG keyring file. Maps to Gradle property `signing.password`.
Note: For documentation on the Gradle properties for Maven deployment, see [Gradle Maven Publish Plugin](https://github.com/vanniktech/gradle-maven-publish-plugin). Note: For documentation on the Gradle properties for Maven deployment, see [Gradle Maven Publish Plugin](https://github.com/vanniktech/gradle-maven-publish-plugin).
Note: Snapshot builds are configured with a Gradle property `IS_SNAPSHOT`. The workflow automatically sets this property to false for release deployments. Note: Snapshot builds are configured with a Gradle property `IS_SNAPSHOT`. The workflow automatically sets this property to false for release deployments.
### Unwedge
* `MAVEN_CENTRAL_USERNAME` — Username for Maven Central, which maps to the Gradle property `mavenCentralUsername`.
* `MAVEN_CENTRAL_PASSWORD` — Password for Maven Central, which maps to the Gradle property `mavenCentralPassword`.

View File

@ -1,7 +1,7 @@
# Speed up builds. Keep these flags here for quick debugging of issues. # Speed up builds. Keep these flags here for quick debugging of issues.
org.gradle.caching=true org.gradle.caching=true
org.gradle.configureondemand=false org.gradle.configureondemand=false
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=1024m
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.vfs.watch=true org.gradle.vfs.watch=true
@ -22,7 +22,7 @@ ZCASH_ASCII_GPG_KEY=
# Configures whether release is an unstable snapshot, therefore published to the snapshot repository. # Configures whether release is an unstable snapshot, therefore published to the snapshot repository.
IS_SNAPSHOT=true IS_SNAPSHOT=true
LIBRARY_VERSION=1.11.0-beta01 LIBRARY_VERSION=1.12.0-beta01
# Kotlin compiler warnings can be considered errors, failing the build. # Kotlin compiler warnings can be considered errors, failing the build.
ZCASH_IS_TREAT_WARNINGS_AS_ERRORS=true ZCASH_IS_TREAT_WARNINGS_AS_ERRORS=true
@ -74,48 +74,50 @@ ANDROID_COMPILE_SDK_VERSION=33
# When changing this, be sure to update .github/actions/setup/action.yml # When changing this, be sure to update .github/actions/setup/action.yml
ANDROID_NDK_VERSION=22.1.7171670 ANDROID_NDK_VERSION=22.1.7171670
ANDROID_GRADLE_PLUGIN_VERSION=7.3.0 ANDROID_GRADLE_PLUGIN_VERSION=7.4.0
DETEKT_VERSION=1.22.0 DETEKT_VERSION=1.22.0
DOKKA_VERSION=1.7.20 DOKKA_VERSION=1.7.20
EMULATOR_WTF_GRADLE_PLUGIN_VERSION=0.0.12 EMULATOR_WTF_GRADLE_PLUGIN_VERSION=0.0.15
FLANK_VERSION=22.10.0 FLANK_VERSION=23.01.0
FULLADLE_VERSION=0.17.4 FULLADLE_VERSION=0.17.4
GRADLE_VERSIONS_PLUGIN_VERSION=0.44.0 GRADLE_VERSIONS_PLUGIN_VERSION=0.44.0
KTLINT_VERSION=0.48.0 KTLINT_VERSION=0.48.0
KSP_VERSION=1.7.21-1.0.8 KSP_VERSION=1.8.0-1.0.8
PROTOBUF_GRADLE_PLUGIN_VERSION=0.8.19 PROTOBUF_GRADLE_PLUGIN_VERSION=0.8.19
RUST_GRADLE_PLUGIN_VERSION=0.9.3 RUST_GRADLE_PLUGIN_VERSION=0.9.3
ANDROIDX_ACTIVITY_VERSION=1.6.1 ANDROIDX_ACTIVITY_VERSION=1.6.1
ANDROIDX_ANNOTATION_VERSION=1.5.0 ANDROIDX_ANNOTATION_VERSION=1.5.0
ANDROIDX_APPCOMPAT_VERSION=1.5.1 ANDROIDX_APPCOMPAT_VERSION=1.6.0
ANDROIDX_COMPOSE_COMPILER_VERSION=1.4.0-alpha02 ANDROIDX_COMPOSE_COMPILER_VERSION=1.4.0
ANDROIDX_COMPOSE_MATERIAL3_VERSION=1.1.0-alpha02 ANDROIDX_COMPOSE_MATERIAL3_VERSION=1.1.0-alpha04
ANDROIDX_COMPOSE_VERSION=1.3.1 ANDROIDX_COMPOSE_VERSION=1.3.3
ANDROIDX_COMPOSE_MATERIAL_ICONS_VERSION=1.3.1
ANDROIDX_CONSTRAINT_LAYOUT_VERSION=2.1.4 ANDROIDX_CONSTRAINT_LAYOUT_VERSION=2.1.4
ANDROIDX_CORE_VERSION=1.9.0 ANDROIDX_CORE_VERSION=1.9.0
ANDROIDX_DATABASE_VERSION=2.2.0 ANDROIDX_DATABASE_VERSION=2.3.0
ANDROIDX_ESPRESSO_VERSION=3.5.0 ANDROIDX_ESPRESSO_VERSION=3.5.1
ANDROIDX_LIFECYCLE_VERSION=2.6.0-alpha03 ANDROIDX_LIFECYCLE_VERSION=2.6.0-alpha04
ANDROIDX_MULTIDEX_VERSION=2.0.1 ANDROIDX_MULTIDEX_VERSION=2.0.1
ANDROIDX_NAVIGATION_VERSION=2.5.3 ANDROIDX_NAVIGATION_VERSION=2.5.3
ANDROIDX_NAVIGATION_COMPOSE_VERSION=2.5.3 ANDROIDX_NAVIGATION_COMPOSE_VERSION=2.5.3
ANDROIDX_NAVIGATION_FRAGMENT_VERSION=2.4.2 ANDROIDX_NAVIGATION_FRAGMENT_VERSION=2.4.2
ANDROIDX_PAGING_VERSION=2.1.2 ANDROIDX_PAGING_VERSION=2.1.2
ANDROIDX_PROFILE_INSTALLER_VERSION=1.3.0-alpha02 ANDROIDX_PROFILE_INSTALLER_VERSION=1.3.0-alpha03
ANDROIDX_ROOM_VERSION=2.4.3 ANDROIDX_ROOM_VERSION=2.5.0
ANDROIDX_SECURITY_CRYPTO_VERSION=1.1.0-alpha04 ANDROIDX_SECURITY_CRYPTO_VERSION=1.1.0-alpha04
ANDROIDX_TEST_JUNIT_VERSION=1.1.4 ANDROIDX_TEST_JUNIT_VERSION=1.1.5
ANDROIDX_TEST_MACROBENCHMARK_VERSION=1.2.0-alpha08 ANDROIDX_TEST_MACROBENCHMARK_VERSION=1.2.0-alpha09
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.4.2 ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.4.2
ANDROIDX_TEST_VERSION=1.5.0 ANDROIDX_TEST_CORE_VERSION=1.5.0
ANDROIDX_TEST_RUNNER_VERSION=1.5.0
ANDROIDX_TRACING_VERSION=1.2.0-alpha01 ANDROIDX_TRACING_VERSION=1.2.0-alpha01
ANDROIDX_UI_AUTOMATOR_VERSION=2.3.0-alpha01 ANDROIDX_UI_AUTOMATOR_VERSION=2.3.0-alpha02
BIP39_VERSION=1.0.4 BIP39_VERSION=1.0.4
COROUTINES_OKHTTP=1.0 COROUTINES_OKHTTP=1.0
GOOGLE_MATERIAL_VERSION=1.7.0 GOOGLE_MATERIAL_VERSION=1.7.0
GRPC_KOTLIN_VERSION=1.3.0 GRPC_KOTLIN_VERSION=1.3.0
GRPC_VERSION=1.51.0 GRPC_VERSION=1.52.1
GSON_VERSION=2.9.0 GSON_VERSION=2.9.0
GUAVA_VERSION=31.1-android GUAVA_VERSION=31.1-android
JACOCO_VERSION=0.8.8 JACOCO_VERSION=0.8.8
@ -123,7 +125,7 @@ JAVAX_ANNOTATION_VERSION=1.3.2
JUNIT_VERSION=5.9.1 JUNIT_VERSION=5.9.1
KOTLINX_COROUTINES_VERSION=1.6.4 KOTLINX_COROUTINES_VERSION=1.6.4
KOTLINX_DATETIME_VERSION=0.4.0 KOTLINX_DATETIME_VERSION=0.4.0
KOTLIN_VERSION=1.7.21 KOTLIN_VERSION=1.8.0
MOCKITO_KOTLIN_VERSION=2.2.0 MOCKITO_KOTLIN_VERSION=2.2.0
MOCKITO_VERSION=4.9.0 MOCKITO_VERSION=4.9.0
PROTOC_VERSION=3.21.11 PROTOC_VERSION=3.21.11

View File

@ -1,18 +1,12 @@
package cash.z.ecc.android.sdk.db package cash.z.ecc.android.sdk.db
import androidx.test.filters.FlakyTest
import androidx.test.filters.MediumTest
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import cash.z.ecc.android.sdk.internal.db.DatabaseCoordinator import cash.z.ecc.android.sdk.internal.db.DatabaseCoordinator
import cash.z.ecc.android.sdk.internal.ext.existsSuspend import cash.z.ecc.android.sdk.internal.ext.existsSuspend
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.test.getAppContext import cash.z.ecc.android.sdk.test.getAppContext
import cash.z.ecc.fixture.DatabaseNameFixture import cash.z.ecc.fixture.DatabaseNameFixture
import cash.z.ecc.fixture.DatabasePathFixture import cash.z.ecc.fixture.DatabasePathFixture
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
@ -33,50 +27,6 @@ class DatabaseCoordinatorTest {
File(noBackupDir).deleteRecursively() File(noBackupDir).deleteRecursively()
} }
// Sanity check of the database coordinator instance and its thread-safe implementation. Our aim
// here is to run two jobs in parallel (the second one runs immediately after the first was started)
// to test mutex implementation and correct DatabaseCoordinator function call result.
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun mutex_test() = runTest {
var testResult: File? = null
launch {
delay(1000)
testResult = dbCoordinator.cacheDbFile(
DatabaseNameFixture.TEST_DB_NETWORK,
DatabaseNameFixture.TEST_DB_ALIAS
)
}
val job2 = launch {
delay(1001)
testResult = dbCoordinator.cacheDbFile(
ZcashNetwork.Mainnet,
"TestZcashSdk"
)
}
advanceTimeBy(1002)
job2.join().also {
assertTrue(testResult != null)
assertTrue(testResult!!.absolutePath.isNotEmpty())
assertTrue(testResult!!.absolutePath.contains(ZcashNetwork.Mainnet.networkName))
assertTrue(testResult!!.absolutePath.contains("TestZcashSdk"))
}
}
@FlakyTest
@Test
@MediumTest
fun mutex_stress_test() {
// We run the mutex test multiple times sequentially to catch a possible problem.
for (x in 0..9) {
mutex_test()
}
}
@Test @Test
@SmallTest @SmallTest
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)

View File

@ -445,7 +445,7 @@ class CompactBlockProcessor internal constructor(
} }
} }
newTxs.onEach { newTransaction -> newTxs.filter { it.minedHeight != null }.onEach { newTransaction ->
enhance(newTransaction) enhance(newTransaction)
} }
twig("Done enhancing transaction details") twig("Done enhancing transaction details")
@ -461,7 +461,9 @@ class CompactBlockProcessor internal constructor(
// TODO [#683]: https://github.com/zcash/zcash-android-wallet-sdk/issues/683 // TODO [#683]: https://github.com/zcash/zcash-android-wallet-sdk/issues/683
private suspend fun enhance(transaction: TransactionOverview) = withContext(Dispatchers.IO) { private suspend fun enhance(transaction: TransactionOverview) = withContext(Dispatchers.IO) {
enhanceHelper(transaction.id, transaction.rawId.byteArray, transaction.minedHeight) transaction.minedHeight?.let { minedHeight ->
enhanceHelper(transaction.id, transaction.rawId.byteArray, minedHeight)
}
} }
private suspend fun enhanceHelper(id: Long, rawTransactionId: ByteArray, minedHeight: BlockHeight) { private suspend fun enhanceHelper(id: Long, rawTransactionId: ByteArray, minedHeight: BlockHeight) {

View File

@ -392,7 +392,7 @@ internal class DatabaseCoordinator private constructor(context: Context) {
* @param databaseFile The database file. * @param databaseFile The database file.
* @return A {@code RoomDatabaseBuilder<T>} which you can use to create the database. * @return A {@code RoomDatabaseBuilder<T>} which you can use to create the database.
*/ */
internal fun <T : RoomDatabase?> commonDatabaseBuilder( internal fun <T : RoomDatabase> commonDatabaseBuilder(
context: Context, context: Context,
klass: Class<T>, klass: Class<T>,
databaseFile: File databaseFile: File

View File

@ -91,12 +91,14 @@ internal fun <T> SupportSQLiteDatabase.queryAndMap(
groupBy(groupBy) groupBy(groupBy)
orderBy(orderBy) orderBy(orderBy)
// Counterintuitive but correct. When using the comma syntax, offset comes first. if (null != limit) {
// When using the keyword syntax, "LIMIT 1 OFFSET 2" then the offset comes second. // Counterintuitive but correct. When using the comma syntax, offset comes first.
if (null == offset) { // When using the keyword syntax, "LIMIT 1 OFFSET 2" then the offset comes second.
limit(limit) if (null == offset) {
} else { limit(limit)
limit(String.format(Locale.ROOT, "%s,%s", offset, limit)) // NON-NLS } else {
limit(String.format(Locale.ROOT, "%s,%s", offset, limit)) // NON-NLS
}
} }
} }

View File

@ -20,10 +20,18 @@ internal class AllTransactionView(
) { ) {
companion object { companion object {
private const val COLUMN_SORT_HEIGHT = "sort_height" // $NON-NLS
private val COLUMNS = arrayOf(
"*", // $NON-NLS
@Suppress("MaxLineLength")
"IFNULL(${AllTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT}, ${UInt.MAX_VALUE}) AS $COLUMN_SORT_HEIGHT" // $NON-NLS
)
private val ORDER_BY = String.format( private val ORDER_BY = String.format(
Locale.ROOT, Locale.ROOT,
"%s DESC, %s DESC", // $NON-NLS "%s DESC, %s DESC", // $NON-NLS
AllTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT, COLUMN_SORT_HEIGHT,
AllTransactionViewDefinition.COLUMN_INTEGER_ID AllTransactionViewDefinition.COLUMN_INTEGER_ID
) )
@ -98,6 +106,7 @@ internal class AllTransactionView(
fun getAllTransactions() = fun getAllTransactions() =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = AllTransactionViewDefinition.VIEW_NAME, table = AllTransactionViewDefinition.VIEW_NAME,
columns = COLUMNS,
orderBy = ORDER_BY, orderBy = ORDER_BY,
cursorParser = cursorParser cursorParser = cursorParser
) )
@ -105,6 +114,7 @@ internal class AllTransactionView(
fun getTransactionRange(blockHeightRange: ClosedRange<BlockHeight>) = fun getTransactionRange(blockHeightRange: ClosedRange<BlockHeight>) =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = AllTransactionViewDefinition.VIEW_NAME, table = AllTransactionViewDefinition.VIEW_NAME,
columns = COLUMNS,
orderBy = ORDER_BY, orderBy = ORDER_BY,
selection = SELECTION_BLOCK_RANGE, selection = SELECTION_BLOCK_RANGE,
selectionArgs = arrayOf(blockHeightRange.start.value, blockHeightRange.endInclusive.value), selectionArgs = arrayOf(blockHeightRange.start.value, blockHeightRange.endInclusive.value),
@ -114,6 +124,7 @@ internal class AllTransactionView(
suspend fun getOldestTransaction() = suspend fun getOldestTransaction() =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = AllTransactionViewDefinition.VIEW_NAME, table = AllTransactionViewDefinition.VIEW_NAME,
columns = COLUMNS,
orderBy = ORDER_BY, orderBy = ORDER_BY,
limit = "1", limit = "1",
cursorParser = cursorParser cursorParser = cursorParser

View File

@ -18,10 +18,18 @@ internal class ReceivedTransactionView(
) { ) {
companion object { companion object {
private const val COLUMN_SORT_HEIGHT = "sort_height" // $NON-NLS
private val COLUMNS = arrayOf(
"*", // $NON-NLS
@Suppress("MaxLineLength")
"IFNULL(${ReceivedTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT}, ${UInt.MAX_VALUE}) AS $COLUMN_SORT_HEIGHT" // $NON-NLS
)
private val ORDER_BY = String.format( private val ORDER_BY = String.format(
Locale.ROOT, Locale.ROOT,
"%s DESC, %s DESC", // $NON-NLS "%s DESC, %s DESC", // $NON-NLS
ReceivedTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT, COLUMN_SORT_HEIGHT,
ReceivedTransactionViewDefinition.COLUMN_INTEGER_ID ReceivedTransactionViewDefinition.COLUMN_INTEGER_ID
) )
@ -37,6 +45,7 @@ internal class ReceivedTransactionView(
fun getReceivedTransactions() = fun getReceivedTransactions() =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = ReceivedTransactionViewDefinition.VIEW_NAME, table = ReceivedTransactionViewDefinition.VIEW_NAME,
columns = COLUMNS,
orderBy = ORDER_BY, orderBy = ORDER_BY,
cursorParser = { cursor -> cursorParser = { cursor ->
val idColumnIndex = cursor.getColumnIndex(ReceivedTransactionViewDefinition.COLUMN_INTEGER_ID) val idColumnIndex = cursor.getColumnIndex(ReceivedTransactionViewDefinition.COLUMN_INTEGER_ID)

View File

@ -18,10 +18,18 @@ internal class SentTransactionView(
) { ) {
companion object { companion object {
private const val COLUMN_SORT_HEIGHT = "sort_height" // $NON-NLS
private val COLUMNS = arrayOf(
"*", // $NON-NLS
@Suppress("MaxLineLength")
"IFNULL(${SentTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT}, ${UInt.MAX_VALUE}) AS $COLUMN_SORT_HEIGHT" // $NON-NLS
)
private val ORDER_BY = String.format( private val ORDER_BY = String.format(
Locale.ROOT, Locale.ROOT,
"%s DESC, %s DESC", // $NON-NLS "%s DESC, %s DESC", // $NON-NLS
SentTransactionViewDefinition.COLUMN_INTEGER_MINED_HEIGHT, COLUMN_SORT_HEIGHT,
SentTransactionViewDefinition.COLUMN_INTEGER_ID SentTransactionViewDefinition.COLUMN_INTEGER_ID
) )
@ -37,6 +45,7 @@ internal class SentTransactionView(
fun getSentTransactions() = fun getSentTransactions() =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = SentTransactionViewDefinition.VIEW_NAME, table = SentTransactionViewDefinition.VIEW_NAME,
columns = COLUMNS,
orderBy = ORDER_BY, orderBy = ORDER_BY,
cursorParser = { cursor -> cursorParser = { cursor ->
val idColumnIndex = cursor.getColumnIndex(SentTransactionViewDefinition.COLUMN_INTEGER_ID) val idColumnIndex = cursor.getColumnIndex(SentTransactionViewDefinition.COLUMN_INTEGER_ID)

View File

@ -4,7 +4,7 @@ sealed class Transaction {
data class Received internal constructor( data class Received internal constructor(
val id: Long, val id: Long,
val rawId: FirstClassByteArray, val rawId: FirstClassByteArray,
val minedHeight: BlockHeight, val minedHeight: BlockHeight?,
val expiryHeight: BlockHeight?, val expiryHeight: BlockHeight?,
val index: Long, val index: Long,
val raw: FirstClassByteArray?, val raw: FirstClassByteArray?,
@ -20,7 +20,7 @@ sealed class Transaction {
data class Sent internal constructor( data class Sent internal constructor(
val id: Long, val id: Long,
val rawId: FirstClassByteArray, val rawId: FirstClassByteArray,
val minedHeight: BlockHeight, val minedHeight: BlockHeight?,
val expiryHeight: BlockHeight?, val expiryHeight: BlockHeight?,
val index: Long, val index: Long,
val raw: FirstClassByteArray?, val raw: FirstClassByteArray?,

View File

@ -9,7 +9,7 @@ package cash.z.ecc.android.sdk.model
data class TransactionOverview internal constructor( data class TransactionOverview internal constructor(
val id: Long, val id: Long,
val rawId: FirstClassByteArray, val rawId: FirstClassByteArray,
val minedHeight: BlockHeight, val minedHeight: BlockHeight?,
val expiryHeight: BlockHeight?, val expiryHeight: BlockHeight?,
val index: Long, val index: Long,
val raw: FirstClassByteArray?, val raw: FirstClassByteArray?,

View File

@ -70,6 +70,7 @@ dependencyResolutionManagement {
val androidxAppcompatVersion = extra["ANDROIDX_APPCOMPAT_VERSION"].toString() val androidxAppcompatVersion = extra["ANDROIDX_APPCOMPAT_VERSION"].toString()
val androidxComposeCompilerVersion = extra["ANDROIDX_COMPOSE_COMPILER_VERSION"].toString() val androidxComposeCompilerVersion = extra["ANDROIDX_COMPOSE_COMPILER_VERSION"].toString()
val androidxComposeMaterial3Version = extra["ANDROIDX_COMPOSE_MATERIAL3_VERSION"].toString() val androidxComposeMaterial3Version = extra["ANDROIDX_COMPOSE_MATERIAL3_VERSION"].toString()
val androidxComposeMaterialIconsVersion = extra["ANDROIDX_COMPOSE_MATERIAL_ICONS_VERSION"].toString()
val androidxComposeVersion = extra["ANDROIDX_COMPOSE_VERSION"].toString() val androidxComposeVersion = extra["ANDROIDX_COMPOSE_VERSION"].toString()
val androidxConstraintLayoutVersion = extra["ANDROIDX_CONSTRAINT_LAYOUT_VERSION"].toString() val androidxConstraintLayoutVersion = extra["ANDROIDX_CONSTRAINT_LAYOUT_VERSION"].toString()
val androidxCoreVersion = extra["ANDROIDX_CORE_VERSION"].toString() val androidxCoreVersion = extra["ANDROIDX_CORE_VERSION"].toString()
@ -87,7 +88,8 @@ dependencyResolutionManagement {
val androidxTestJunitVersion = extra["ANDROIDX_TEST_JUNIT_VERSION"].toString() val androidxTestJunitVersion = extra["ANDROIDX_TEST_JUNIT_VERSION"].toString()
val androidxTestMacrobenchmarkVersion = extra["ANDROIDX_TEST_MACROBENCHMARK_VERSION"].toString() val androidxTestMacrobenchmarkVersion = extra["ANDROIDX_TEST_MACROBENCHMARK_VERSION"].toString()
val androidxTestOrchestratorVersion = extra["ANDROIDX_TEST_ORCHESTRATOR_VERSION"].toString() val androidxTestOrchestratorVersion = extra["ANDROIDX_TEST_ORCHESTRATOR_VERSION"].toString()
val androidxTestVersion = extra["ANDROIDX_TEST_VERSION"].toString() val androidxTestCoreVersion = extra["ANDROIDX_TEST_CORE_VERSION"].toString()
val androidxTestRunnerVersion = extra["ANDROIDX_TEST_RUNNER_VERSION"].toString()
val androidxTracingVersion = extra["ANDROIDX_TRACING_VERSION"].toString() val androidxTracingVersion = extra["ANDROIDX_TRACING_VERSION"].toString()
val androidxUiAutomatorVersion = extra["ANDROIDX_UI_AUTOMATOR_VERSION"].toString() val androidxUiAutomatorVersion = extra["ANDROIDX_UI_AUTOMATOR_VERSION"].toString()
val bip39Version = extra["BIP39_VERSION"].toString() val bip39Version = extra["BIP39_VERSION"].toString()
@ -159,7 +161,7 @@ dependencyResolutionManagement {
library("guava", "com.google.guava:guava:$guavaVersion") library("guava", "com.google.guava:guava:$guavaVersion")
library("javax-annotation", "javax.annotation:javax.annotation-api:$javaxAnnotationVersion") library("javax-annotation", "javax.annotation:javax.annotation-api:$javaxAnnotationVersion")
library("kotlin-reflect", "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion") library("kotlin-reflect", "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
library("kotlin-stdlib", "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") library("kotlin-stdlib", "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
library("kotlinx-coroutines-android", "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxCoroutinesVersion") library("kotlinx-coroutines-android", "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxCoroutinesVersion")
library("kotlinx-coroutines-core", "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion") library("kotlinx-coroutines-core", "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
library("kotlinx-datetime", "org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDateTimeVersion") library("kotlinx-datetime", "org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDateTimeVersion")
@ -169,8 +171,8 @@ dependencyResolutionManagement {
// Demo app // Demo app
library("androidx-compose-foundation", "androidx.compose.foundation:foundation:$androidxComposeVersion") library("androidx-compose-foundation", "androidx.compose.foundation:foundation:$androidxComposeVersion")
library("androidx-compose-material3", "androidx.compose.material3:material3:$androidxComposeMaterial3Version") library("androidx-compose-material3", "androidx.compose.material3:material3:$androidxComposeMaterial3Version")
library("androidx-compose-material-icons-core", "androidx.compose.material:material-icons-core:$androidxComposeVersion") library("androidx-compose-material-icons-core", "androidx.compose.material:material-icons-core:$androidxComposeMaterialIconsVersion")
library("androidx-compose-material-icons-extended", "androidx.compose.material:material-icons-extended:$androidxComposeVersion") library("androidx-compose-material-icons-extended", "androidx.compose.material:material-icons-extended:$androidxComposeMaterialIconsVersion")
library("androidx-compose-tooling", "androidx.compose.ui:ui-tooling:$androidxComposeVersion") library("androidx-compose-tooling", "androidx.compose.ui:ui-tooling:$androidxComposeVersion")
library("androidx-compose-ui", "androidx.compose.ui:ui:$androidxComposeVersion") library("androidx-compose-ui", "androidx.compose.ui:ui:$androidxComposeVersion")
library("androidx-compose-ui-fonts", "androidx.compose.ui:ui-text-google-fonts:$androidxComposeVersion") library("androidx-compose-ui-fonts", "androidx.compose.ui:ui-text-google-fonts:$androidxComposeVersion")
@ -183,10 +185,10 @@ dependencyResolutionManagement {
library("androidx-espresso-contrib", "androidx.test.espresso:espresso-contrib:$androidxEspressoVersion") library("androidx-espresso-contrib", "androidx.test.espresso:espresso-contrib:$androidxEspressoVersion")
library("androidx-espresso-core", "androidx.test.espresso:espresso-core:$androidxEspressoVersion") library("androidx-espresso-core", "androidx.test.espresso:espresso-core:$androidxEspressoVersion")
library("androidx-espresso-intents", "androidx.test.espresso:espresso-intents:$androidxEspressoVersion") library("androidx-espresso-intents", "androidx.test.espresso:espresso-intents:$androidxEspressoVersion")
library("androidx-test-core", "androidx.test:core:$androidxTestVersion") library("androidx-test-core", "androidx.test:core:$androidxTestCoreVersion")
library("androidx-test-junit", "androidx.test.ext:junit:$androidxTestJunitVersion") library("androidx-test-junit", "androidx.test.ext:junit:$androidxTestJunitVersion")
library("androidx-test-macrobenchmark", "androidx.benchmark:benchmark-macro-junit4:$androidxTestMacrobenchmarkVersion") library("androidx-test-macrobenchmark", "androidx.benchmark:benchmark-macro-junit4:$androidxTestMacrobenchmarkVersion")
library("androidx-test-runner", "androidx.test:runner:$androidxTestVersion") library("androidx-test-runner", "androidx.test:runner:$androidxTestRunnerVersion")
library("androidx-test-orchestrator", "androidx.test:orchestrator:$androidxTestOrchestratorVersion") library("androidx-test-orchestrator", "androidx.test:orchestrator:$androidxTestOrchestratorVersion")
library("androidx-tracing", "androidx.tracing:tracing:$androidxTracingVersion") library("androidx-tracing", "androidx.tracing:tracing:$androidxTracingVersion")
library("androidx-uiAutomator", "androidx.test.uiautomator:uiautomator:$androidxUiAutomatorVersion") library("androidx-uiAutomator", "androidx.test.uiautomator:uiautomator:$androidxUiAutomatorVersion")