Compare commits

...

16 Commits

Author SHA1 Message Date
Pacu 0ce078109b
Merge 919aa65a10 into b29e1a3e43 2024-04-23 13:28:56 +02:00
dependabot[bot] b29e1a3e43
Bump actions/download-artifact from 4.1.5 to 4.1.6 (#1452)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](8caf195ad4...9c19ed7fe5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 12:43:17 +02:00
dependabot[bot] f812cee61d
Bump actions/upload-artifact from 4.3.2 to 4.3.3 (#1451)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](1746f4ab65...65462800fd)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 12:42:58 +02:00
dependabot[bot] dc4c2a3958
Bump actions/checkout from 4.1.2 to 4.1.3 (#1450)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](9bb56186c3...1d96c772d1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 12:42:04 +02:00
str4d 59f4fef479
Rust dependency updates (#1445)
* Bump Rust to 1.77

* cargo update

* Migrate from `failure` to `anyhow` for error handling

* `dlopen2 0.7`

* Remove extra comma

Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>

---------

Co-authored-by: Honza Rychnovský <rychnovsky.honza@gmail.com>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-04-20 15:22:24 +02:00
dependabot[bot] dceab7f6e7
Bump gradle/wrapper-validation-action from 3.3.0 to 3.3.1 (#1448)
Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/gradle/wrapper-validation-action/releases)
- [Commits](460a3ca55f...5188e9b552)

---
updated-dependencies:
- dependency-name: gradle/wrapper-validation-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 12:01:07 +02:00
dependabot[bot] 5ef0434f0c
Bump actions/download-artifact from 4.1.4 to 4.1.5 (#1447)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.4 to 4.1.5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](c850b930e6...8caf195ad4)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 12:00:52 +02:00
dependabot[bot] 2e40a8c0f4
Bump actions/upload-artifact from 4.3.1 to 4.3.2 (#1446)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](5d5d22a312...1746f4ab65)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 12:00:39 +02:00
Honza Rychnovský 2a3c070a01
Remove logs stripping check entirely (#1444)
- As ensuring the check should be applied is not possible for a library that depends on clients build type and their different use cases
- Stripping tested manually with different client wallets, and it works as expected
2024-04-17 17:51:31 +02:00
Honza Rychnovský 1833e866a7
Improve logs stripping test (#1443)
This change avoids false-positives in clients
2024-04-17 14:25:28 +02:00
Honza Rychnovský 652487e563
[#1435] Eliminate logging with Proguard
- Closes #1435
- Changelog update
2024-04-17 09:26:39 +02:00
Honza Rychnovský 2c09776f9f
[#1440] Db image malformed while scanning blocks 2024-04-17 09:24:49 +02:00
Honza Rychnovský 6a96fa3d78
[#1438] Dependency update
* [#1438] Gradle 8.7

* AndroidX + Kotlin 1.9.23

* AGP 8.3.0

* Detekt 1.23.6 + Detekt Compose 0.3.15

* Dokka 1.9.20

* FooJay 0.8.0

* Ktlint 1.2.1

* Bip-39 1.0.8

* Remove coroutines-okhttp dependency

* Google Material 1.11.0

* gRPC Java 1.63.0

Removed `enableFullStreamDecompression()` as it had no effect as described in https://github.com/grpc/grpc-java/releases/tag/v1.61.0

* Gson 2.10.1

* Jacoco 0.8.12

* JUnit 5.10.2

* Kotlinx Coroutines 1.8.0

* Kotlin Immutable Collections 0.3.7

* Mockito 5.11.0

Removed unnecessary Mockito Kotlin dependency

* Protoc 4.26.1

* Changelog update

* Bump lib version

To produce a new snapshot version
2024-04-15 17:43:19 +02:00
dependabot[bot] 96b99be791
Bump gradle/wrapper-validation-action from 2.1.3 to 3.3.0 (#1437)
Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 2.1.3 to 3.3.0.
- [Release notes](https://github.com/gradle/wrapper-validation-action/releases)
- [Commits](b5418f5a58...460a3ca55f)

---
updated-dependencies:
- dependency-name: gradle/wrapper-validation-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-15 09:19:55 +02:00
Kris Nuttycombe 7dadd57d6b
Provide the pool type when retrieving a memo. (#1436)
* WIP: Provide the pool type when retrieving a memo.

* Gitignore new idea file

* Let TypesafeBackend work with typesafe class

* Query and use protocol for memo obtaining

---------

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
2024-04-14 21:28:07 +02:00
Francisco Gindre 919aa65a10
[#397] Add ZIP 321 URI parser
adds a transaction proposal API for URI strings

Closes #397

Add `proposeFulfillingPaymentUri` to changelog
2024-03-08 22:23:39 -03:00
46 changed files with 831 additions and 641 deletions

View File

@ -18,12 +18,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
# Gradle Wrapper validation can be flaky # Gradle Wrapper validation can be flaky
# https://github.com/gradle/wrapper-validation-action/issues/40 # https://github.com/gradle/wrapper-validation-action/issues/40
- name: Gradle Wrapper Validation - name: Gradle Wrapper Validation
timeout-minutes: 1 timeout-minutes: 1
uses: gradle/wrapper-validation-action@b5418f5a58f5fd2eb486dd7efb368fe7be7eae45 uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af
check_secrets: check_secrets:
environment: deployment environment: deployment
@ -51,7 +51,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 50 timeout-minutes: 50
@ -86,7 +86,7 @@ jobs:
zip -r ${BINARIES_ZIP_PATH} . -i *build/outputs/* zip -r ${BINARIES_ZIP_PATH} . -i *build/outputs/*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 10 timeout-minutes: 10
with: with:
name: Release binaries name: Release binaries

View File

@ -28,12 +28,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
# Gradle Wrapper validation can be flaky # Gradle Wrapper validation can be flaky
# https://github.com/gradle/wrapper-validation-action/issues/40 # https://github.com/gradle/wrapper-validation-action/issues/40
- name: Gradle Wrapper Validation - name: Gradle Wrapper Validation
timeout-minutes: 1 timeout-minutes: 1
uses: gradle/wrapper-validation-action@b5418f5a58f5fd2eb486dd7efb368fe7be7eae45 uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af
check_secrets: check_secrets:
environment: deployment environment: deployment
@ -59,7 +59,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 50 timeout-minutes: 50
@ -93,7 +93,7 @@ jobs:
zip -r ${BINARIES_ZIP_PATH} . -i *build/outputs/* zip -r ${BINARIES_ZIP_PATH} . -i *build/outputs/*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 10 timeout-minutes: 10
with: with:
name: Snapshot binaries name: Snapshot binaries

View File

@ -29,12 +29,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
# Gradle Wrapper validation can be flaky # Gradle Wrapper validation can be flaky
# https://github.com/gradle/wrapper-validation-action/issues/40 # https://github.com/gradle/wrapper-validation-action/issues/40
- name: Gradle Wrapper Validation - name: Gradle Wrapper Validation
timeout-minutes: 1 timeout-minutes: 1
uses: gradle/wrapper-validation-action@b5418f5a58f5fd2eb486dd7efb368fe7be7eae45 uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af
check_firebase_secrets: check_firebase_secrets:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -68,7 +68,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 10 timeout-minutes: 10
@ -86,7 +86,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -107,7 +107,7 @@ jobs:
zip -r ${REPORTS_ZIP_PATH} . -i build/reports/detekt/\* zip -r ${REPORTS_ZIP_PATH} . -i build/reports/detekt/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Detekt static analysis results name: Detekt static analysis results
@ -121,7 +121,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -142,7 +142,7 @@ jobs:
zip -r ${REPORTS_ZIP_PATH} . -i build/reports/ktlint/\* zip -r ${REPORTS_ZIP_PATH} . -i build/reports/ktlint/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Ktlint static analysis results name: Ktlint static analysis results
@ -156,7 +156,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -179,7 +179,7 @@ jobs:
zip -r ${LINT_ZIP_PATH} . -i \*build/reports/\* zip -r ${LINT_ZIP_PATH} . -i \*build/reports/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Android Lint static analysis results name: Android Lint static analysis results
@ -193,7 +193,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -214,7 +214,7 @@ jobs:
zip -r ${TEST_RESULTS_ZIP_PATH} . -i \*/build/test-results/\* \*/build/reports/\* zip -r ${TEST_RESULTS_ZIP_PATH} . -i \*/build/test-results/\* \*/build/reports/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Test Android modules with Unit Tests name: Test Android modules with Unit Tests
@ -231,7 +231,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -271,7 +271,7 @@ jobs:
zip -r ${TEST_RESULTS_ZIP_PATH} . -i build/fladle/\* \*/build/outputs/androidTest-results/\* zip -r ${TEST_RESULTS_ZIP_PATH} . -i build/fladle/\* \*/build/outputs/androidTest-results/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Test Android modules with FTL results name: Test Android modules with FTL results
@ -286,7 +286,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -309,7 +309,7 @@ jobs:
zip -r ${TEST_RESULTS_ZIP_PATH} . -i \*/build/test-results/\* zip -r ${TEST_RESULTS_ZIP_PATH} . -i \*/build/test-results/\*
- name: Upload Artifacts - name: Upload Artifacts
if: ${{ always() }} if: ${{ always() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Test Android modules with WTF results name: Test Android modules with WTF results
@ -323,7 +323,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -355,7 +355,7 @@ jobs:
zip -r ${BINARIES_ZIP_PATH} . -i demo-app/build/outputs/apk/\*/release/\*.apk demo-app/build/outputs/bundle/\*/release/\*.aab zip -r ${BINARIES_ZIP_PATH} . -i demo-app/build/outputs/apk/\*/release/\*.apk demo-app/build/outputs/bundle/\*/release/\*.aab
zip -r ${MAPPINGS_ZIP_PATH} . -i demo-app/build/outputs/mapping/\*/mapping.txt zip -r ${MAPPINGS_ZIP_PATH} . -i demo-app/build/outputs/mapping/\*/mapping.txt
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
timeout-minutes: 1 timeout-minutes: 1
with: with:
name: Demo app release binaries name: Demo app release binaries
@ -373,7 +373,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
timeout-minutes: 1 timeout-minutes: 1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f
- name: Setup - name: Setup
id: setup id: setup
timeout-minutes: 30 timeout-minutes: 30
@ -388,7 +388,7 @@ jobs:
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'
- name: Download a single artifact - name: Download a single artifact
uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395
with: with:
name: Demo app release binaries name: Demo app release binaries
- name: Robo test - name: Robo test

1
.gitignore vendored
View File

@ -52,6 +52,7 @@ captures/
.idea/protoeditor.xml .idea/protoeditor.xml
.idea/appInsightsSettings.xml .idea/appInsightsSettings.xml
.idea/migrations.xml .idea/migrations.xml
.idea/deploymentTargetSelector.xml
*.iml *.iml
# Keystore files # Keystore files

View File

@ -6,6 +6,13 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Changed
- The SDK components no longer contain logging statements in the release build
- Gradle 8.7
- Android Gradle Plugin 8.3.0
- Kotlin 1.9.23
- Other dependencies update
## [2.1.0] - 2024-04-09 ## [2.1.0] - 2024-04-09
### Added ### Added
@ -53,6 +60,7 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
transactions. transactions.
- `Synchronizer.proposeTransfer` - `Synchronizer.proposeTransfer`
- `Synchronizer.proposeShielding` - `Synchronizer.proposeShielding`
- `Synchronizer.proposeFulfillingPaymentUri`
- `Synchronizer.createProposedTransactions` - `Synchronizer.createProposedTransactions`
- `WalletBalanceFixture` class with mock values that are supposed to be used only for testing purposes - `WalletBalanceFixture` class with mock values that are supposed to be used only for testing purposes
- `Memo.countLength(memoString: String)` to count memo length in bytes - `Memo.countLength(memoString: String)` to count memo length in bytes

369
backend-lib/Cargo.lock generated
View File

@ -2,21 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aead" name = "aead"
version = "0.5.2" version = "0.5.2"
@ -52,24 +37,24 @@ dependencies = [
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.2" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.16" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.80" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]] [[package]]
name = "arrayref" name = "arrayref"
@ -85,24 +70,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "base58" name = "base58"
@ -165,9 +135,9 @@ dependencies = [
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.4.2" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "bitvec" name = "bitvec"
@ -227,9 +197,9 @@ dependencies = [
[[package]] [[package]]
name = "bs58" name = "bs58"
version = "0.5.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [ dependencies = [
"sha2", "sha2",
"tinyvec", "tinyvec",
@ -237,9 +207,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.15.4" version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -249,9 +219,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.5.0" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]] [[package]]
name = "cbc" name = "cbc"
@ -264,9 +234,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.90" version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
[[package]] [[package]]
name = "cesu8" name = "cesu8"
@ -317,9 +287,9 @@ dependencies = [
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.6" version = "4.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
dependencies = [ dependencies = [
"bytes", "bytes",
"memchr", "memchr",
@ -421,9 +391,9 @@ dependencies = [
[[package]] [[package]]
name = "dlopen2" name = "dlopen2"
version = "0.6.1" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bc2c7ed06fd72a8513ded8d0d2f6fd2655a85d6885c48cae8625d80faf28c03" checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6"
dependencies = [ dependencies = [
"dlopen2_derive", "dlopen2_derive",
"libc", "libc",
@ -439,7 +409,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -453,9 +423,9 @@ dependencies = [
[[package]] [[package]]
name = "either" name = "either"
version = "1.10.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]] [[package]]
name = "equihash" name = "equihash"
@ -492,28 +462,6 @@ dependencies = [
"blake2b_simd", "blake2b_simd",
] ]
[[package]]
name = "failure"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
"backtrace",
"failure_derive",
]
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"synstructure",
]
[[package]] [[package]]
name = "fallible-iterator" name = "fallible-iterator"
version = "0.2.0" version = "0.2.0"
@ -528,9 +476,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]] [[package]]
name = "ff" name = "ff"
@ -581,21 +529,15 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi", "wasi",
] ]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]] [[package]]
name = "group" name = "group"
version = "0.13.0" version = "0.13.0"
@ -694,9 +636,9 @@ dependencies = [
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
@ -739,9 +681,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.5" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -758,18 +700,18 @@ dependencies = [
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.11.0" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [ dependencies = [
"either", "either",
] ]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "jni" name = "jni"
@ -896,9 +838,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.1" version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]] [[package]]
name = "memuse" name = "memuse"
@ -915,26 +857,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]] [[package]]
name = "multimap" name = "multimap"
version = "0.8.3" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
[[package]] [[package]]
name = "ndk-sys" name = "ndk-sys"
version = "0.3.0" version = "0.5.0+25.2.9519653"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
dependencies = [ dependencies = [
"jni-sys", "jni-sys",
] ]
@ -1010,15 +943,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.19.0"
@ -1078,9 +1002,9 @@ dependencies = [
[[package]] [[package]]
name = "paranoid-android" name = "paranoid-android"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e736c9fbaf42b43459cd1fded3dd272968daadfcbc5660ee231a12899f092289" checksum = "101795d63d371b43e38d6e7254677657be82f17022f7f7893c268f33ac0caadc"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"ndk-sys", "ndk-sys",
@ -1144,9 +1068,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
@ -1179,28 +1103,28 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.16" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.78" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "prost" name = "prost"
version = "0.12.3" version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922"
dependencies = [ dependencies = [
"bytes", "bytes",
"prost-derive", "prost-derive",
@ -1208,9 +1132,9 @@ dependencies = [
[[package]] [[package]]
name = "prost-build" name = "prost-build"
version = "0.12.3" version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" checksum = "80b776a1b2dc779f5ee0641f8ade0125bc1298dd41a9a0c16d8bd57b42d222b1"
dependencies = [ dependencies = [
"bytes", "bytes",
"heck", "heck",
@ -1223,38 +1147,37 @@ dependencies = [
"prost", "prost",
"prost-types", "prost-types",
"regex", "regex",
"syn 2.0.52", "syn",
"tempfile", "tempfile",
"which",
] ]
[[package]] [[package]]
name = "prost-derive" name = "prost-derive"
version = "0.12.3" version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools", "itertools",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
name = "prost-types" name = "prost-types"
version = "0.12.3" version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe"
dependencies = [ dependencies = [
"prost", "prost",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1297,9 +1220,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [ dependencies = [
"either", "either",
"rayon-core", "rayon-core",
@ -1348,9 +1271,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.3" version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -1371,9 +1294,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "ring" name = "ring"
@ -1414,17 +1337,11 @@ dependencies = [
"time", "time",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.31" version = "0.38.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"errno", "errno",
@ -1526,22 +1443,22 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -1566,9 +1483,9 @@ dependencies = [
[[package]] [[package]]
name = "shardtree" name = "shardtree"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d766257c56a1bdd75479c256b97c92e72788a9afb18b5199f58faf7188dc99d9" checksum = "3b3cdd24424ce0b381646737fedddc33c4dcf7dcd2d545056b53f7982097bef5"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"either", "either",
@ -1578,9 +1495,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.1" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "spin" name = "spin"
@ -1602,38 +1519,15 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "syn"
version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"unicode-xid",
]
[[package]] [[package]]
name = "tap" name = "tap"
version = "1.0.1" version = "1.0.1"
@ -1654,22 +1548,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.57" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.57" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -1684,9 +1578,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.34" version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
@ -1705,9 +1599,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.17" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [ dependencies = [
"num-conv", "num-conv",
"time-core", "time-core",
@ -1738,7 +1632,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"prost-build", "prost-build",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -1760,7 +1654,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -1831,12 +1725,6 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
version = "0.5.1" version = "0.5.1"
@ -1855,9 +1743,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.7.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
[[package]] [[package]]
name = "valuable" name = "valuable"
@ -1914,7 +1802,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1936,7 +1824,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2015,7 +1903,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -2035,17 +1923,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.4", "windows_i686_gnu 0.52.5",
"windows_i686_msvc 0.52.4", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.4", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -2056,9 +1945,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -2068,9 +1957,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -2080,9 +1969,15 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -2092,9 +1987,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -2104,9 +1999,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -2116,9 +2011,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -2128,9 +2023,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "wyz" name = "wyz"
@ -2151,8 +2046,8 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
name = "zcash-android-wallet-sdk" name = "zcash-android-wallet-sdk"
version = "0.0.4" version = "0.0.4"
dependencies = [ dependencies = [
"anyhow",
"dlopen2", "dlopen2",
"failure",
"hdwallet", "hdwallet",
"hdwallet-bitcoin", "hdwallet-bitcoin",
"hex", "hex",
@ -2418,7 +2313,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]
@ -2438,7 +2333,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.52", "syn",
] ]
[[package]] [[package]]

View File

@ -8,14 +8,12 @@ authors = [
description = "JNI backend for the Android wallet SDK" description = "JNI backend for the Android wallet SDK"
publish = false publish = false
edition = "2018" edition = "2018"
rust-version = "1.75" rust-version = "1.77"
[dependencies] [dependencies]
failure = "0.1"
hdwallet = "0.4" hdwallet = "0.4"
hdwallet-bitcoin = "0.4" hdwallet-bitcoin = "0.4"
hex = "0.4" hex = "0.4"
jni = { version = "0.21", default-features = false }
orchard = "0.8" orchard = "0.8"
prost = "0.12" prost = "0.12"
rusqlite = "0.29" rusqlite = "0.29"
@ -32,6 +30,10 @@ zcash_proofs = "0.15"
# Initialization # Initialization
rayon = "1.7" rayon = "1.7"
# JNI
anyhow = "1"
jni = { version = "0.21", default-features = false }
# Logging # Logging
log-panics = "2.0.0" log-panics = "2.0.0"
paranoid-android = "0.2" paranoid-android = "0.2"
@ -39,7 +41,7 @@ tracing = "0.1"
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
# Conditional access to newer NDK features # Conditional access to newer NDK features
dlopen2 = "0.6" dlopen2 = "0.7"
libc = "0.2" libc = "0.2"
## Uncomment this to test librustzcash changes locally ## Uncomment this to test librustzcash changes locally

View File

@ -28,6 +28,11 @@ interface Backend {
memo: ByteArray? = byteArrayOf() memo: ByteArray? = byteArrayOf()
): ProposalUnsafe ): ProposalUnsafe
suspend fun proposeTransferFromUri(
account: Int,
uri: String
): ProposalUnsafe
suspend fun proposeShielding( suspend fun proposeShielding(
account: Int, account: Int,
shieldingThreshold: Long, shieldingThreshold: Long,
@ -94,6 +99,7 @@ interface Backend {
@Throws(RuntimeException::class) @Throws(RuntimeException::class)
suspend fun getMemoAsUtf8( suspend fun getMemoAsUtf8(
txId: ByteArray, txId: ByteArray,
protocol: Int,
outputIndex: Int outputIndex: Int
): String? ): String?

View File

@ -125,11 +125,13 @@ class RustBackend private constructor(
override suspend fun getMemoAsUtf8( override suspend fun getMemoAsUtf8(
txId: ByteArray, txId: ByteArray,
protocol: Int,
outputIndex: Int outputIndex: Int
) = withContext(SdkDispatchers.DATABASE_IO) { ) = withContext(SdkDispatchers.DATABASE_IO) {
getMemoAsUtf8( getMemoAsUtf8(
dataDbFile.absolutePath, dataDbFile.absolutePath,
txId, txId,
protocol,
outputIndex, outputIndex,
networkId = networkId networkId = networkId
) )
@ -300,6 +302,22 @@ class RustBackend private constructor(
) )
} }
override suspend fun proposeTransferFromUri(
account: Int,
uri: String
): ProposalUnsafe =
withContext(SdkDispatchers.DATABASE_IO) {
ProposalUnsafe.parse(
proposeTransferFromUri(
dataDbFile.absolutePath,
account,
uri,
networkId = networkId,
useZip317Fees = IS_USE_ZIP_317_FEES
)
)
}
override suspend fun proposeTransfer( override suspend fun proposeTransfer(
account: Int, account: Int,
to: String, to: String,
@ -501,6 +519,7 @@ class RustBackend private constructor(
private external fun getMemoAsUtf8( private external fun getMemoAsUtf8(
dbDataPath: String, dbDataPath: String,
txId: ByteArray, txId: ByteArray,
poolType: Int,
outputIndex: Int, outputIndex: Int,
networkId: Int networkId: Int
): String? ): String?
@ -600,6 +619,16 @@ class RustBackend private constructor(
networkId: Int networkId: Int
) )
@JvmStatic
@Suppress("LongParameterList")
private external fun proposeTransferFromUri(
dbDataPath: String,
account: Int,
uri: String,
networkId: Int,
useZip317Fees: Boolean
): ByteArray
@JvmStatic @JvmStatic
@Suppress("LongParameterList") @Suppress("LongParameterList")
private external fun proposeTransfer( private external fun proposeTransfer(

View File

@ -0,0 +1,41 @@
package cash.z.ecc.android.sdk.internal.model
/**
* An enumeration of supported Zcash protocols.
*/
@Suppress("MagicNumber")
enum class ZcashProtocol {
TRANSPARENT {
override val poolCode = 0
},
SAPLING {
override val poolCode = 2
},
ORCHARD {
override val poolCode = 3
};
abstract val poolCode: Int
fun isShielded() = this == SAPLING || this == ORCHARD
companion object {
fun validate(poolTypeCode: Int): Boolean {
return when (poolTypeCode) {
TRANSPARENT.poolCode,
SAPLING.poolCode,
ORCHARD.poolCode -> true
else -> false
}
}
fun fromPoolType(poolCode: Int): ZcashProtocol {
return when (poolCode) {
TRANSPARENT.poolCode -> TRANSPARENT
SAPLING.poolCode -> SAPLING
ORCHARD.poolCode -> ORCHARD
else -> error("Unsupported pool type: $poolCode")
}
}
}
}

View File

@ -5,7 +5,7 @@ use std::panic;
use std::path::Path; use std::path::Path;
use std::ptr; use std::ptr;
use failure::format_err; use anyhow::anyhow;
use jni::objects::{JByteArray, JObject, JObjectArray, JValue}; use jni::objects::{JByteArray, JObject, JObjectArray, JValue};
use jni::{ use jni::{
objects::{JClass, JString}, objects::{JClass, JString},
@ -87,27 +87,27 @@ fn wallet_db<P: Parameters>(
env: &mut JNIEnv, env: &mut JNIEnv,
params: P, params: P,
db_data: JString, db_data: JString,
) -> Result<WalletDb<rusqlite::Connection, P>, failure::Error> { ) -> anyhow::Result<WalletDb<rusqlite::Connection, P>> {
WalletDb::for_path(utils::java_string_to_rust(env, &db_data), params) WalletDb::for_path(utils::java_string_to_rust(env, &db_data), params)
.map_err(|e| format_err!("Error opening wallet database connection: {}", e)) .map_err(|e| anyhow!("Error opening wallet database connection: {}", e))
} }
fn block_db(env: &mut JNIEnv, fsblockdb_root: JString) -> Result<FsBlockDb, failure::Error> { fn block_db(env: &mut JNIEnv, fsblockdb_root: JString) -> anyhow::Result<FsBlockDb> {
FsBlockDb::for_path(utils::java_string_to_rust(env, &fsblockdb_root)) FsBlockDb::for_path(utils::java_string_to_rust(env, &fsblockdb_root))
.map_err(|e| format_err!("Error opening block source database connection: {:?}", e)) .map_err(|e| anyhow!("Error opening block source database connection: {:?}", e))
} }
fn account_id_from_jint(account: jint) -> Result<zip32::AccountId, failure::Error> { fn account_id_from_jint(account: jint) -> anyhow::Result<zip32::AccountId> {
u32::try_from(account) u32::try_from(account)
.map_err(|_| ()) .map_err(|_| ())
.and_then(|id| zip32::AccountId::try_from(id).map_err(|_| ())) .and_then(|id| zip32::AccountId::try_from(id).map_err(|_| ()))
.map_err(|_| format_err!("Invalid account ID")) .map_err(|_| anyhow!("Invalid account ID"))
} }
fn account_id_from_jni<'local, P: Parameters>( fn account_id_from_jni<'local, P: Parameters>(
db_data: &WalletDb<rusqlite::Connection, P>, db_data: &WalletDb<rusqlite::Connection, P>,
account_index: jint, account_index: jint,
) -> Result<AccountId, failure::Error> { ) -> anyhow::Result<AccountId> {
let requested_account_index = account_id_from_jint(account_index)?; let requested_account_index = account_id_from_jint(account_index)?;
// Find the single account matching the given ZIP 32 account index. // Find the single account matching the given ZIP 32 account index.
@ -118,7 +118,7 @@ fn account_id_from_jni<'local, P: Parameters>(
db_data db_data
.get_account(account_id) .get_account(account_id)
.map_err(|e| { .map_err(|e| {
format_err!( anyhow!(
"Database error encountered retrieving account {:?}: {}", "Database error encountered retrieving account {:?}: {}",
account_id, account_id,
e e
@ -126,7 +126,7 @@ fn account_id_from_jni<'local, P: Parameters>(
}) })
.and_then(|acct_opt| .and_then(|acct_opt|
acct_opt.ok_or_else(|| acct_opt.ok_or_else(||
format_err!( anyhow!(
"Wallet data corrupted: unable to retrieve account data for account {:?}", "Wallet data corrupted: unable to retrieve account data for account {:?}",
account_id account_id
) )
@ -140,8 +140,8 @@ fn account_id_from_jni<'local, P: Parameters>(
match (accounts.next(), accounts.next()) { match (accounts.next(), accounts.next()) {
(Some(account), None) => Ok(account?.id()), (Some(account), None) => Ok(account?.id()),
(None, None) => Err(format_err!("Account does not exist")), (None, None) => Err(anyhow!("Account does not exist")),
(_, Some(_)) => Err(format_err!("Account index matches more than one account")), (_, Some(_)) => Err(anyhow!("Account index matches more than one account")),
} }
} }
@ -201,10 +201,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_initBlock
match init_blockmeta_db(&mut db_meta) { match init_blockmeta_db(&mut db_meta) {
Ok(()) => Ok(0), Ok(()) => Ok(0),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!("Error while initializing block metadata DB: {}", e)),
"Error while initializing block metadata DB: {}",
e
)),
} }
}); });
unwrap_exc_or(&mut env, res, -1) unwrap_exc_or(&mut env, res, -1)
@ -229,7 +226,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_initDataD
let res = catch_unwind(&mut env, |env| { let res = catch_unwind(&mut env, |env| {
let network = parse_network(network_id as u32)?; let network = parse_network(network_id as u32)?;
let mut db_data = wallet_db(env, network, db_data) let mut db_data = wallet_db(env, network, db_data)
.map_err(|e| format_err!("Error while opening data DB: {}", e))?; .map_err(|e| anyhow!("Error while opening data DB: {}", e))?;
let seed = (!seed.is_null()).then(|| SecretVec::new(env.convert_byte_array(seed).unwrap())); let seed = (!seed.is_null()).then(|| SecretVec::new(env.convert_byte_array(seed).unwrap()));
@ -251,7 +248,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_initDataD
{ {
Ok(2) Ok(2)
} }
Err(e) => Err(format_err!("Error while initializing data DB: {}", e)), Err(e) => Err(anyhow!("Error while initializing data DB: {}", e)),
} }
}); });
unwrap_exc_or(&mut env, res, -1) unwrap_exc_or(&mut env, res, -1)
@ -271,17 +268,17 @@ fn encode_usk<'a>(
) )
} }
fn decode_usk(env: &JNIEnv, usk: JByteArray) -> Result<UnifiedSpendingKey, failure::Error> { fn decode_usk(env: &JNIEnv, usk: JByteArray) -> anyhow::Result<UnifiedSpendingKey> {
let usk_bytes = SecretVec::new(env.convert_byte_array(usk).unwrap()); let usk_bytes = SecretVec::new(env.convert_byte_array(usk).unwrap());
// The remainder of the function is safe. // The remainder of the function is safe.
UnifiedSpendingKey::from_bytes(Era::Orchard, usk_bytes.expose_secret()).map_err(|e| match e { UnifiedSpendingKey::from_bytes(Era::Orchard, usk_bytes.expose_secret()).map_err(|e| match e {
DecodingError::EraMismatch(era) => format_err!( DecodingError::EraMismatch(era) => anyhow!(
"Spending key was from era {:?}, but {:?} was expected.", "Spending key was from era {:?}, but {:?} was expected.",
era, era,
Era::Orchard Era::Orchard
), ),
e => format_err!( e => anyhow!(
"An error occurred decoding the provided unified spending key: {:?}", "An error occurred decoding the provided unified spending key: {:?}",
e e
), ),
@ -321,22 +318,22 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_createAcc
let mut db_data = wallet_db(env, network, db_data)?; let mut db_data = wallet_db(env, network, db_data)?;
let seed = SecretVec::new(env.convert_byte_array(seed).unwrap()); let seed = SecretVec::new(env.convert_byte_array(seed).unwrap());
let treestate = TreeState::decode(&env.convert_byte_array(treestate).unwrap()[..]) let treestate = TreeState::decode(&env.convert_byte_array(treestate).unwrap()[..])
.map_err(|e| format_err!("Invalid TreeState: {}", e))?; .map_err(|e| anyhow!("Invalid TreeState: {}", e))?;
let recover_until = recover_until.try_into().ok(); let recover_until = recover_until.try_into().ok();
let birthday = let birthday =
AccountBirthday::from_treestate(treestate, recover_until).map_err(|e| match e { AccountBirthday::from_treestate(treestate, recover_until).map_err(|e| match e {
BirthdayError::HeightInvalid(e) => { BirthdayError::HeightInvalid(e) => {
format_err!("Invalid TreeState: Invalid height: {}", e) anyhow!("Invalid TreeState: Invalid height: {}", e)
} }
BirthdayError::Decode(e) => { BirthdayError::Decode(e) => {
format_err!("Invalid TreeState: Invalid frontier encoding: {}", e) anyhow!("Invalid TreeState: Invalid frontier encoding: {}", e)
} }
})?; })?;
let (account_id, usk) = db_data let (account_id, usk) = db_data
.create_account(&seed, &birthday) .create_account(&seed, &birthday)
.map_err(|e| format_err!("Error while initializing accounts: {}", e))?; .map_err(|e| anyhow!("Error while initializing accounts: {}", e))?;
let account = db_data.get_account(account_id)?.expect("just created"); let account = db_data.get_account(account_id)?.expect("just created");
let account_index = match account.source() { let account_index = match account.source() {
@ -396,7 +393,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustDerivationTool_de
let account = account_id_from_jint(account)?; let account = account_id_from_jint(account)?;
let usk = UnifiedSpendingKey::from_seed(&network, seed.expose_secret(), account) let usk = UnifiedSpendingKey::from_seed(&network, seed.expose_secret(), account)
.map_err(|e| format_err!("error generating unified spending key from seed: {:?}", e))?; .map_err(|e| anyhow!("error generating unified spending key from seed: {:?}", e))?;
Ok(encode_usk(env, account, usk)?.into_raw()) Ok(encode_usk(env, account, usk)?.into_raw())
}); });
@ -421,16 +418,16 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustDerivationTool_de
let accounts = if accounts > 0 { let accounts = if accounts > 0 {
accounts as u32 accounts as u32
} else { } else {
return Err(format_err!("accounts argument must be greater than zero")); return Err(anyhow!("accounts argument must be greater than zero"));
}; };
let ufvks: Vec<_> = (0..accounts) let ufvks: Vec<_> = (0..accounts)
.map(|account| { .map(|account| {
let account_id = zip32::AccountId::try_from(account) let account_id = zip32::AccountId::try_from(account)
.map_err(|_| format_err!("Invalid account ID"))?; .map_err(|_| anyhow!("Invalid account ID"))?;
UnifiedSpendingKey::from_seed(&network, &seed, account_id) UnifiedSpendingKey::from_seed(&network, &seed, account_id)
.map_err(|e| { .map_err(|e| {
format_err!("error generating unified spending key from seed: {:?}", e) anyhow!("error generating unified spending key from seed: {:?}", e)
}) })
.map(|usk| usk.to_unified_full_viewing_key().encode(&network)) .map(|usk| usk.to_unified_full_viewing_key().encode(&network))
}) })
@ -466,7 +463,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustDerivationTool_de
let account_id = account_id_from_jint(account_index)?; let account_id = account_id_from_jint(account_index)?;
let ufvk = UnifiedSpendingKey::from_seed(&network, &seed, account_id) let ufvk = UnifiedSpendingKey::from_seed(&network, &seed, account_id)
.map_err(|e| format_err!("error generating unified spending key from seed: {:?}", e)) .map_err(|e| anyhow!("error generating unified spending key from seed: {:?}", e))
.map(|usk| usk.to_unified_full_viewing_key())?; .map(|usk| usk.to_unified_full_viewing_key())?;
let (ua, _) = ufvk let (ua, _) = ufvk
@ -498,7 +495,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustDerivationTool_de
let ufvk = match UnifiedFullViewingKey::decode(&network, &ufvk_string) { let ufvk = match UnifiedFullViewingKey::decode(&network, &ufvk_string) {
Ok(ufvk) => ufvk, Ok(ufvk) => ufvk,
Err(e) => { Err(e) => {
return Err(format_err!( return Err(anyhow!(
"Error while deriving viewing key from string input: {}", "Error while deriving viewing key from string input: {}",
e, e,
)); ));
@ -564,8 +561,8 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getCurren
.expect("Couldn't create Java string!"); .expect("Couldn't create Java string!");
Ok(output.into_raw()) Ok(output.into_raw())
} }
Ok(None) => Err(format_err!("{:?} is not known to the wallet", account)), Ok(None) => Err(anyhow!("{:?} is not known to the wallet", account)),
Err(e) => Err(format_err!("Error while fetching address: {}", e)), Err(e) => Err(anyhow!("Error while fetching address: {}", e)),
} }
}); });
@ -575,14 +572,14 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getCurren
struct UnifiedAddressParser(UnifiedAddress); struct UnifiedAddressParser(UnifiedAddress);
impl zcash_address::TryFromRawAddress for UnifiedAddressParser { impl zcash_address::TryFromRawAddress for UnifiedAddressParser {
type Error = failure::Error; type Error = anyhow::Error;
fn try_from_raw_unified( fn try_from_raw_unified(
data: zcash_address::unified::Address, data: zcash_address::unified::Address,
) -> Result<Self, zcash_address::ConversionError<Self::Error>> { ) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
data.try_into() data.try_into()
.map(UnifiedAddressParser) .map(UnifiedAddressParser)
.map_err(|e| format_err!("Invalid Unified Address: {}", e).into()) .map_err(|e| anyhow!("Invalid Unified Address: {}", e).into())
} }
} }
@ -603,8 +600,8 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getTransp
let (network, ua) = match ZcashAddress::try_from_encoded(&ua_str) { let (network, ua) = match ZcashAddress::try_from_encoded(&ua_str) {
Ok(addr) => addr Ok(addr) => addr
.convert::<(_, UnifiedAddressParser)>() .convert::<(_, UnifiedAddressParser)>()
.map_err(|e| format_err!("Not a Unified Address: {}", e)), .map_err(|e| anyhow!("Not a Unified Address: {}", e)),
Err(e) => return Err(format_err!("Invalid Zcash address: {}", e)), Err(e) => return Err(anyhow!("Invalid Zcash address: {}", e)),
}?; }?;
if let Some(taddr) = ua.0.transparent() { if let Some(taddr) = ua.0.transparent() {
@ -622,7 +619,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getTransp
.expect("Couldn't create Java string!"); .expect("Couldn't create Java string!");
Ok(output.into_raw()) Ok(output.into_raw())
} else { } else {
Err(format_err!( Err(anyhow!(
"Unified Address doesn't contain a transparent receiver" "Unified Address doesn't contain a transparent receiver"
)) ))
} }
@ -647,8 +644,8 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getSaplin
let (network, ua) = match ZcashAddress::try_from_encoded(&ua_str) { let (network, ua) = match ZcashAddress::try_from_encoded(&ua_str) {
Ok(addr) => addr Ok(addr) => addr
.convert::<(_, UnifiedAddressParser)>() .convert::<(_, UnifiedAddressParser)>()
.map_err(|e| format_err!("Not a Unified Address: {}", e)), .map_err(|e| anyhow!("Not a Unified Address: {}", e)),
Err(e) => return Err(format_err!("Invalid Zcash address: {}", e)), Err(e) => return Err(anyhow!("Invalid Zcash address: {}", e)),
}?; }?;
if let Some(addr) = ua.0.sapling() { if let Some(addr) = ua.0.sapling() {
@ -657,7 +654,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getSaplin
.expect("Couldn't create Java string!"); .expect("Couldn't create Java string!");
Ok(output.into_raw()) Ok(output.into_raw())
} else { } else {
Err(format_err!( Err(anyhow!(
"Unified Address doesn't contain a Sapling receiver" "Unified Address doesn't contain a Sapling receiver"
)) ))
} }
@ -700,7 +697,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_isValidSa
Address::Sapling(_) => Ok(JNI_TRUE), Address::Sapling(_) => Ok(JNI_TRUE),
Address::Transparent(_) | Address::Unified(_) => Ok(JNI_FALSE), Address::Transparent(_) | Address::Unified(_) => Ok(JNI_FALSE),
}, },
None => Err(format_err!("Address is for the wrong network")), None => Err(anyhow!("Address is for the wrong network")),
} }
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -725,7 +722,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_isValidTr
Address::Sapling(_) | Address::Unified(_) => Ok(JNI_FALSE), Address::Sapling(_) | Address::Unified(_) => Ok(JNI_FALSE),
Address::Transparent(_) => Ok(JNI_TRUE), Address::Transparent(_) => Ok(JNI_TRUE),
}, },
None => Err(format_err!("Address is for the wrong network")), None => Err(anyhow!("Address is for the wrong network")),
} }
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -750,7 +747,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_isValidUn
Address::Unified(_) => Ok(JNI_TRUE), Address::Unified(_) => Ok(JNI_TRUE),
Address::Sapling(_) | Address::Transparent(_) => Ok(JNI_FALSE), Address::Sapling(_) | Address::Transparent(_) => Ok(JNI_FALSE),
}, },
None => Err(format_err!("Address is for the wrong network")), None => Err(anyhow!("Address is for the wrong network")),
} }
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -777,21 +774,21 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getTotalT
let amount = (&db_data) let amount = (&db_data)
.get_target_and_anchor_heights(min_confirmations) .get_target_and_anchor_heights(min_confirmations)
.map_err(|e| format_err!("Error while fetching anchor height: {}", e)) .map_err(|e| anyhow!("Error while fetching anchor height: {}", e))
.and_then(|opt_anchor| { .and_then(|opt_anchor| {
opt_anchor opt_anchor
.map(|(target, _)| target) // Include unconfirmed funds. .map(|(target, _)| target) // Include unconfirmed funds.
.ok_or(format_err!("Anchor height not available; scan required.")) .ok_or(anyhow!("Anchor height not available; scan required."))
}) })
.and_then(|anchor| { .and_then(|anchor| {
(&db_data) (&db_data)
.get_unspent_transparent_outputs(&taddr, anchor, &[]) .get_unspent_transparent_outputs(&taddr, anchor, &[])
.map_err(|e| format_err!("Error while fetching verified balance: {}", e)) .map_err(|e| anyhow!("Error while fetching verified balance: {}", e))
})? })?
.iter() .iter()
.map(|utxo| utxo.txout().value) .map(|utxo| utxo.txout().value)
.sum::<Option<NonNegativeAmount>>() .sum::<Option<NonNegativeAmount>>()
.ok_or_else(|| format_err!("Balance overflowed MAX_MONEY"))?; .ok_or_else(|| anyhow!("Balance overflowed MAX_MONEY"))?;
Ok(Amount::from(amount).into()) Ok(Amount::from(amount).into())
}); });
@ -799,12 +796,21 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getTotalT
unwrap_exc_or(&mut env, res, -1) unwrap_exc_or(&mut env, res, -1)
} }
fn parse_protocol(code: i32) -> Option<ShieldedProtocol> {
match code {
2 => Some(ShieldedProtocol::Sapling),
3 => Some(ShieldedProtocol::Orchard),
_ => None,
}
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getMemoAsUtf8<'local>( pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getMemoAsUtf8<'local>(
mut env: JNIEnv<'local>, mut env: JNIEnv<'local>,
_: JClass<'local>, _: JClass<'local>,
db_data: JString<'local>, db_data: JString<'local>,
txid_bytes: JByteArray<'local>, txid_bytes: JByteArray<'local>,
pool_type: jint,
output_index: jint, output_index: jint,
network_id: jint, network_id: jint,
) -> jstring { ) -> jstring {
@ -815,16 +821,18 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getMemoAs
let txid_bytes = env.convert_byte_array(txid_bytes)?; let txid_bytes = env.convert_byte_array(txid_bytes)?;
let txid = TxId::read(&txid_bytes[..])?; let txid = TxId::read(&txid_bytes[..])?;
let protocol = parse_protocol(pool_type)
.ok_or(anyhow!("Shielded protocol not recognized: {}", pool_type))?;
let output_index = u16::try_from(output_index)?; let output_index = u16::try_from(output_index)?;
let memo = (&db_data) let memo = (&db_data)
.get_memo(NoteId::new(txid, ShieldedProtocol::Sapling, output_index)) .get_memo(NoteId::new(txid, protocol, output_index))
.map_err(|e| format_err!("An error occurred retrieving the memo, {}", e)) .map_err(|e| anyhow!("An error occurred retrieving the memo, {}", e))
.and_then(|memo| match memo { .and_then(|memo| match memo {
Some(Memo::Empty) => Ok("".to_string()), Some(Memo::Empty) => Ok("".to_string()),
Some(Memo::Text(memo)) => Ok(memo.into()), Some(Memo::Text(memo)) => Ok(memo.into()),
None => Err(format_err!("Memo not available")), None => Err(anyhow!("Memo not available")),
_ => Err(format_err!("This memo does not contain UTF-8 text")), _ => Err(anyhow!("This memo does not contain UTF-8 text")),
})?; })?;
let output = env.new_string(memo).expect("Couldn't create Java string!"); let output = env.new_string(memo).expect("Couldn't create Java string!");
@ -849,8 +857,8 @@ fn encode_blockmeta<'a>(env: &mut JNIEnv<'a>, meta: BlockMeta) -> jni::errors::R
) )
} }
fn decode_blockmeta(env: &mut JNIEnv, obj: JObject) -> Result<BlockMeta, failure::Error> { fn decode_blockmeta(env: &mut JNIEnv, obj: JObject) -> anyhow::Result<BlockMeta> {
fn long_as_u32(env: &mut JNIEnv, obj: &JObject, name: &str) -> Result<u32, failure::Error> { fn long_as_u32(env: &mut JNIEnv, obj: &JObject, name: &str) -> anyhow::Result<u32> {
Ok(u32::try_from(env.get_field(obj, name, "J")?.j()?)?) Ok(u32::try_from(env.get_field(obj, name, "J")?.j()?)?)
} }
@ -858,7 +866,7 @@ fn decode_blockmeta(env: &mut JNIEnv, obj: JObject) -> Result<BlockMeta, failure
env: &mut JNIEnv, env: &mut JNIEnv,
obj: &JObject, obj: &JObject,
name: &str, name: &str,
) -> Result<[u8; N], failure::Error> { ) -> anyhow::Result<[u8; N]> {
let field = JByteArray::from(env.get_field(obj, name, "[B")?.l()?); let field = JByteArray::from(env.get_field(obj, name, "[B")?.l()?);
Ok(env.convert_byte_array(field)?[..].try_into()?) Ok(env.convert_byte_array(field)?[..].try_into()?)
} }
@ -900,7 +908,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_writeBloc
match block_db.write_block_metadata(&block_meta) { match block_db.write_block_metadata(&block_meta) {
Ok(()) => Ok(JNI_TRUE), Ok(()) => Ok(JNI_TRUE),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Failed to write block metadata to FsBlockDb: {:?}", "Failed to write block metadata to FsBlockDb: {:?}",
e e
)), )),
@ -925,7 +933,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getLatest
Ok(Some(block_height)) => Ok(i64::from(u32::from(block_height))), Ok(Some(block_height)) => Ok(i64::from(u32::from(block_height))),
// Use -1 to return null across the FFI. // Use -1 to return null across the FFI.
Ok(None) => Ok(-1), Ok(None) => Ok(-1),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Failed to read block metadata from FsBlockDb: {:?}", "Failed to read block metadata from FsBlockDb: {:?}",
e e
)), )),
@ -949,7 +957,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_findBlock
match block_db.find_block(height) { match block_db.find_block(height) {
Ok(Some(meta)) => Ok(encode_blockmeta(env, meta)?.into_raw()), Ok(Some(meta)) => Ok(encode_blockmeta(env, meta)?.into_raw()),
Ok(None) => Ok(ptr::null_mut()), Ok(None) => Ok(ptr::null_mut()),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Failed to read block metadata from FsBlockDb: {:?}", "Failed to read block metadata from FsBlockDb: {:?}",
e e
)), )),
@ -973,7 +981,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_rewindBlo
let height = BlockHeight::try_from(height)?; let height = BlockHeight::try_from(height)?;
block_db.truncate_to_height(height).map_err(|e| { block_db.truncate_to_height(height).map_err(|e| {
format_err!( anyhow!(
"Error while rewinding block metadata DB to height {}: {}", "Error while rewinding block metadata DB to height {}: {}",
height, height,
e e
@ -1011,7 +1019,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getNeares
)) ))
} }
Ok(None) => Ok(height as i64), Ok(None) => Ok(height as i64),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Error while getting nearest rewind height for {}: {}", "Error while getting nearest rewind height for {}: {}",
height, height,
e e
@ -1040,7 +1048,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_rewindToH
db_data db_data
.truncate_to_height(height) .truncate_to_height(height)
.map(|_| 1) .map(|_| 1)
.map_err(|e| format_err!("Error while rewinding data DB to height {}: {}", height, e)) .map_err(|e| anyhow!("Error while rewinding data DB to height {}: {}", height, e))
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -1050,12 +1058,12 @@ fn decode_subtree_root<H>(
env: &mut JNIEnv, env: &mut JNIEnv,
obj: JObject, obj: JObject,
node_parser: impl FnOnce(&[u8]) -> std::io::Result<H>, node_parser: impl FnOnce(&[u8]) -> std::io::Result<H>,
) -> Result<CommitmentTreeRoot<H>, failure::Error> { ) -> anyhow::Result<CommitmentTreeRoot<H>> {
fn long_as_u32(env: &mut JNIEnv, obj: &JObject, name: &str) -> Result<u32, failure::Error> { fn long_as_u32(env: &mut JNIEnv, obj: &JObject, name: &str) -> anyhow::Result<u32> {
Ok(u32::try_from(env.get_field(obj, name, "J")?.j()?)?) Ok(u32::try_from(env.get_field(obj, name, "J")?.j()?)?)
} }
fn byte_array(env: &mut JNIEnv, obj: &JObject, name: &str) -> Result<Vec<u8>, failure::Error> { fn byte_array(env: &mut JNIEnv, obj: &JObject, name: &str) -> anyhow::Result<Vec<u8>> {
let field = JByteArray::from(env.get_field(obj, name, "[B")?.l()?); let field = JByteArray::from(env.get_field(obj, name, "[B")?.l()?);
Ok(env.convert_byte_array(field)?[..].try_into()?) Ok(env.convert_byte_array(field)?[..].try_into()?)
} }
@ -1086,7 +1094,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_putSubtre
env: &mut JNIEnv, env: &mut JNIEnv,
roots: JObjectArray, roots: JObjectArray,
node_parser: impl Fn(&[u8]) -> std::io::Result<H>, node_parser: impl Fn(&[u8]) -> std::io::Result<H>,
) -> Result<Vec<CommitmentTreeRoot<H>>, failure::Error> { ) -> anyhow::Result<Vec<CommitmentTreeRoot<H>>> {
let count = env.get_array_length(&roots).unwrap(); let count = env.get_array_length(&roots).unwrap();
(0..count) (0..count)
.scan(env, |env, i| { .scan(env, |env, i| {
@ -1102,14 +1110,14 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_putSubtre
let sapling_start_index = if sapling_start_index >= 0 { let sapling_start_index = if sapling_start_index >= 0 {
sapling_start_index as u64 sapling_start_index as u64
} else { } else {
return Err(format_err!("Sapling start index must be nonnegative.")); return Err(anyhow!("Sapling start index must be nonnegative."));
}; };
let sapling_roots = parse_roots(env, sapling_roots, |n| sapling::Node::read(n))?; let sapling_roots = parse_roots(env, sapling_roots, |n| sapling::Node::read(n))?;
let orchard_start_index = if orchard_start_index >= 0 { let orchard_start_index = if orchard_start_index >= 0 {
orchard_start_index as u64 orchard_start_index as u64
} else { } else {
return Err(format_err!("Orchard start index must be nonnegative.")); return Err(anyhow!("Orchard start index must be nonnegative."));
}; };
let orchard_roots = parse_roots(env, orchard_roots, |n| { let orchard_roots = parse_roots(env, orchard_roots, |n| {
orchard::tree::MerkleHashOrchard::read(n) orchard::tree::MerkleHashOrchard::read(n)
@ -1117,11 +1125,11 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_putSubtre
db_data db_data
.put_sapling_subtree_roots(sapling_start_index, &sapling_roots) .put_sapling_subtree_roots(sapling_start_index, &sapling_roots)
.map_err(|e| format_err!("Error while storing Sapling subtree roots: {}", e))?; .map_err(|e| anyhow!("Error while storing Sapling subtree roots: {}", e))?;
db_data db_data
.put_orchard_subtree_roots(orchard_start_index, &orchard_roots) .put_orchard_subtree_roots(orchard_start_index, &orchard_roots)
.map_err(|e| format_err!("Error while storing Orchard subtree roots: {}", e))?; .map_err(|e| anyhow!("Error while storing Orchard subtree roots: {}", e))?;
Ok(JNI_TRUE) Ok(JNI_TRUE)
}); });
@ -1146,7 +1154,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_updateCha
db_data db_data
.update_chain_tip(height) .update_chain_tip(height)
.map(|()| JNI_TRUE) .map(|()| JNI_TRUE)
.map_err(|e| format_err!("Error while updating chain tip to height {}: {}", height, e)) .map_err(|e| anyhow!("Error while updating chain tip to height {}: {}", height, e))
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -1170,7 +1178,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getFullyS
Ok(Some(metadata)) => Ok(i64::from(u32::from(metadata.block_height()))), Ok(Some(metadata)) => Ok(i64::from(u32::from(metadata.block_height()))),
// Use -1 to return null across the FFI. // Use -1 to return null across the FFI.
Ok(None) => Ok(-1), Ok(None) => Ok(-1),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Failed to read block metadata from WalletDb: {:?}", "Failed to read block metadata from WalletDb: {:?}",
e e
)), )),
@ -1197,7 +1205,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getMaxSca
Ok(Some(metadata)) => Ok(i64::from(u32::from(metadata.block_height()))), Ok(Some(metadata)) => Ok(i64::from(u32::from(metadata.block_height()))),
// Use -1 to return null across the FFI. // Use -1 to return null across the FFI.
Ok(None) => Ok(-1), Ok(None) => Ok(-1),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Failed to read block metadata from WalletDb: {:?}", "Failed to read block metadata from WalletDb: {:?}",
e e
)), )),
@ -1253,7 +1261,7 @@ fn encode_wallet_summary<'a, P: Parameters>(
env: &mut JNIEnv<'a>, env: &mut JNIEnv<'a>,
db_data: &WalletDb<rusqlite::Connection, P>, db_data: &WalletDb<rusqlite::Connection, P>,
summary: WalletSummary<AccountId>, summary: WalletSummary<AccountId>,
) -> Result<JObject<'a>, failure::Error> { ) -> anyhow::Result<JObject<'a>> {
let account_balances = utils::rust_vec_to_java( let account_balances = utils::rust_vec_to_java(
env, env,
summary summary
@ -1268,7 +1276,7 @@ fn encode_wallet_summary<'a, P: Parameters>(
AccountSource::Derived { account_index, .. } => account_index, AccountSource::Derived { account_index, .. } => account_index,
AccountSource::Imported => unreachable!("Imported accounts are unimplemented"), AccountSource::Imported => unreachable!("Imported accounts are unimplemented"),
}; };
Ok::<_, failure::Error>((account_index, balance)) Ok::<_, anyhow::Error>((account_index, balance))
}) })
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
JNI_ACCOUNT_BALANCE, JNI_ACCOUNT_BALANCE,
@ -1310,7 +1318,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_getWallet
match db_data match db_data
.get_wallet_summary(ANCHOR_OFFSET_U32) .get_wallet_summary(ANCHOR_OFFSET_U32)
.map_err(|e| format_err!("Error while fetching scan progress: {}", e))? .map_err(|e| anyhow!("Error while fetching scan progress: {}", e))?
.filter(|summary| { .filter(|summary| {
summary summary
.scan_progress() .scan_progress()
@ -1362,7 +1370,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_suggestSc
let ranges = db_data let ranges = db_data
.suggest_scan_ranges() .suggest_scan_ranges()
.map_err(|e| format_err!("Error while fetching suggested scan ranges: {}", e))?; .map_err(|e| anyhow!("Error while fetching suggested scan ranges: {}", e))?;
Ok(utils::rust_vec_to_java( Ok(utils::rust_vec_to_java(
env, env,
@ -1384,7 +1392,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_suggestSc
fn encode_scan_summary<'a>( fn encode_scan_summary<'a>(
env: &mut JNIEnv<'a>, env: &mut JNIEnv<'a>,
scan_summary: ScanSummary, scan_summary: ScanSummary,
) -> Result<JObject<'a>, failure::Error> { ) -> anyhow::Result<JObject<'a>> {
let scanned_range = scan_summary.scanned_range(); let scanned_range = scan_summary.scanned_range();
Ok(env.new_object( Ok(env.new_object(
"cash/z/ecc/android/sdk/internal/model/JniScanSummary", "cash/z/ecc/android/sdk/internal/model/JniScanSummary",
@ -1416,7 +1424,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_scanBlock
let mut db_data = wallet_db(env, network, db_data)?; let mut db_data = wallet_db(env, network, db_data)?;
let from_height = BlockHeight::try_from(from_height)?; let from_height = BlockHeight::try_from(from_height)?;
let from_state = TreeState::decode(&env.convert_byte_array(from_state).unwrap()[..]) let from_state = TreeState::decode(&env.convert_byte_array(from_state).unwrap()[..])
.map_err(|e| format_err!("Invalid TreeState: {}", e))? .map_err(|e| anyhow!("Invalid TreeState: {}", e))?
.to_chain_state()?; .to_chain_state()?;
let limit = usize::try_from(limit)?; let limit = usize::try_from(limit)?;
@ -1429,7 +1437,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_scanBlock
limit, limit,
) { ) {
Ok(scan_summary) => Ok(encode_scan_summary(env, scan_summary)?.into_raw()), Ok(scan_summary) => Ok(encode_scan_summary(env, scan_summary)?.into_raw()),
Err(e) => Err(format_err!( Err(e) => Err(anyhow!(
"Rust error while scanning blocks (limit {:?}): {}", "Rust error while scanning blocks (limit {:?}): {}",
limit, limit,
e e
@ -1471,17 +1479,17 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_putUtxo<'
OutPoint::new(txid, index as u32), OutPoint::new(txid, index as u32),
TxOut { TxOut {
value: NonNegativeAmount::from_nonnegative_i64(value) value: NonNegativeAmount::from_nonnegative_i64(value)
.map_err(|_| format_err!("Invalid UTXO value"))?, .map_err(|_| anyhow!("Invalid UTXO value"))?,
script_pubkey, script_pubkey,
}, },
BlockHeight::from(height as u32), BlockHeight::from(height as u32),
) )
.ok_or_else(|| format_err!("UTXO is not P2PKH or P2SH"))?; .ok_or_else(|| anyhow!("UTXO is not P2PKH or P2SH"))?;
debug!("Storing UTXO in db_data"); debug!("Storing UTXO in db_data");
match db_data.put_received_transparent_utxo(&output) { match db_data.put_received_transparent_utxo(&output) {
Ok(_) => Ok(JNI_TRUE), Ok(_) => Ok(JNI_TRUE),
Err(e) => Err(format_err!("Error while inserting UTXO: {}", e)), Err(e) => Err(anyhow!("Error while inserting UTXO: {}", e)),
} }
}); });
unwrap_exc_or(&mut env, res, JNI_FALSE) unwrap_exc_or(&mut env, res, JNI_FALSE)
@ -1512,7 +1520,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_decryptAn
match decrypt_and_store_transaction(&network, &mut db_data, &tx) { match decrypt_and_store_transaction(&network, &mut db_data, &tx) {
Ok(()) => Ok(JNI_TRUE), Ok(()) => Ok(JNI_TRUE),
Err(e) => Err(format_err!("Error while decrypting transaction: {}", e)), Err(e) => Err(anyhow!("Error while decrypting transaction: {}", e)),
} }
}); });
@ -1535,6 +1543,49 @@ fn zip317_helper<DbT>(
) )
} }
#[no_mangle]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTransferFromUri<'local>(
mut env: JNIEnv<'local>,
_: JClass<'local>,
db_data: JString<'local>,
account: jint,
payment_uri: JString<'local>,
network_id: jint,
use_zip317_fees: jboolean,
) -> jbyteArray {
let res = catch_unwind(&mut env, |env| {
let _span = tracing::info_span!("RustBackend.proposeTransfer").entered();
let network = parse_network(network_id as u32)?;
let mut db_data = wallet_db(env, network, db_data)?;
let account = account_id_from_jint(account)?;
let payment_uri = utils::java_string_to_rust(env, &payment_uri);
let input_selector = zip317_helper(None, use_zip317_fees);
let request = TransactionRequest::from_uri(&network, &payment_uri)
.map_err(|e| format_err!("Error creating transaction request: {:?}", e))?;
let proposal = propose_transfer::<_, _, _, Infallible>(
&mut db_data,
&network,
account,
&input_selector,
request,
ANCHOR_OFFSET,
)
.map_err(|e| format_err!("Error creating transaction proposal: {}", e))?;
utils::rust_bytes_to_java(
&env,
Proposal::from_standard_proposal(&network, &proposal)
.encode_to_vec()
.as_ref(),
)
.map(|arr| arr.into_raw())
});
unwrap_exc_or(&mut env, res, ptr::null_mut())
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTransfer<'local>( pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTransfer<'local>(
mut env: JNIEnv<'local>, mut env: JNIEnv<'local>,
@ -1554,13 +1605,13 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTr
let account = account_id_from_jni(&db_data, account)?; let account = account_id_from_jni(&db_data, account)?;
let to = utils::java_string_to_rust(env, &to); let to = utils::java_string_to_rust(env, &to);
let value = NonNegativeAmount::from_nonnegative_i64(value) let value = NonNegativeAmount::from_nonnegative_i64(value)
.map_err(|_| format_err!("Invalid amount, out of range"))?; .map_err(|_| anyhow!("Invalid amount, out of range"))?;
let memo_bytes = env.convert_byte_array(memo).unwrap(); let memo_bytes = env.convert_byte_array(memo).unwrap();
let to = match Address::decode(&network, &to) { let to = match Address::decode(&network, &to) {
Some(to) => to, Some(to) => to,
None => { None => {
return Err(format_err!("Address is for the wrong network")); return Err(anyhow!("Address is for the wrong network"));
} }
}; };
@ -1568,7 +1619,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTr
let memo = match to { let memo = match to {
Address::Sapling(_) | Address::Unified(_) => { Address::Sapling(_) | Address::Unified(_) => {
let memo_value = let memo_value =
Memo::from_bytes(&memo_bytes).map_err(|_| format_err!("Invalid memo"))?; Memo::from_bytes(&memo_bytes).map_err(|_| anyhow!("Invalid memo"))?;
Some(MemoBytes::from(&memo_value)) Some(MemoBytes::from(&memo_value))
} }
Address::Transparent(_) => None, Address::Transparent(_) => None,
@ -1584,7 +1635,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTr
message: None, message: None,
other_params: vec![], other_params: vec![],
}]) }])
.map_err(|e| format_err!("Error creating transaction request: {:?}", e))?; .map_err(|e| anyhow!("Error creating transaction request: {:?}", e))?;
let proposal = propose_transfer::<_, _, _, Infallible>( let proposal = propose_transfer::<_, _, _, Infallible>(
&mut db_data, &mut db_data,
@ -1594,7 +1645,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeTr
request, request,
ANCHOR_OFFSET, ANCHOR_OFFSET,
) )
.map_err(|e| format_err!("Error creating transaction proposal: {}", e))?; .map_err(|e| anyhow!("Error creating transaction proposal: {}", e))?;
Ok(utils::rust_bytes_to_java( Ok(utils::rust_bytes_to_java(
&env, &env,
@ -1625,18 +1676,18 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeSh
let mut db_data = wallet_db(env, network, db_data)?; let mut db_data = wallet_db(env, network, db_data)?;
let account = account_id_from_jni(&db_data, account)?; let account = account_id_from_jni(&db_data, account)?;
let shielding_threshold = NonNegativeAmount::from_nonnegative_i64(shielding_threshold) let shielding_threshold = NonNegativeAmount::from_nonnegative_i64(shielding_threshold)
.map_err(|_| format_err!("Invalid shielding threshold, out of range"))?; .map_err(|_| anyhow!("Invalid shielding threshold, out of range"))?;
let memo_bytes = env.convert_byte_array(memo).unwrap(); let memo_bytes = env.convert_byte_array(memo).unwrap();
let transparent_receiver = let transparent_receiver =
match utils::java_nullable_string_to_rust(env, &transparent_receiver) { match utils::java_nullable_string_to_rust(env, &transparent_receiver) {
None => Ok(None), None => Ok(None),
Some(addr) => match Address::decode(&network, &addr) { Some(addr) => match Address::decode(&network, &addr) {
None => Err(format_err!("Transparent receiver is for the wrong network")), None => Err(anyhow!("Transparent receiver is for the wrong network")),
Some(addr) => match addr { Some(addr) => match addr {
Address::Sapling(_) | Address::Unified(_) => Err(format_err!( Address::Sapling(_) | Address::Unified(_) => {
"Transparent receiver is not a transparent address" Err(anyhow!("Transparent receiver is not a transparent address"))
)), }
Address::Transparent(addr) => { Address::Transparent(addr) => {
if db_data if db_data
.get_transparent_receivers(account)? .get_transparent_receivers(account)?
@ -1644,9 +1695,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeSh
{ {
Ok(Some(addr)) Ok(Some(addr))
} else { } else {
Err(format_err!( Err(anyhow!("Transparent receiver does not belong to account"))
"Transparent receiver does not belong to account",
))
} }
} }
}, },
@ -1658,17 +1707,17 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeSh
let account_receivers = db_data let account_receivers = db_data
.get_target_and_anchor_heights(min_confirmations_for_heights) .get_target_and_anchor_heights(min_confirmations_for_heights)
.map_err(|e| format_err!("Error while fetching anchor height: {}", e)) .map_err(|e| anyhow!("Error while fetching anchor height: {}", e))
.and_then(|opt_anchor| { .and_then(|opt_anchor| {
opt_anchor opt_anchor
.map(|(target, _)| target) // Include unconfirmed funds. .map(|(target, _)| target) // Include unconfirmed funds.
.ok_or(format_err!("Anchor height not available; scan required.")) .ok_or(anyhow!("Anchor height not available; scan required."))
}) })
.and_then(|anchor| { .and_then(|anchor| {
db_data db_data
.get_transparent_balances(account, anchor) .get_transparent_balances(account, anchor)
.map_err(|e| { .map_err(|e| {
format_err!( anyhow!(
"Error while fetching transparent balances for {:?}: {}", "Error while fetching transparent balances for {:?}: {}",
account, account,
e e
@ -1678,7 +1727,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeSh
let from_addrs = if let Some((addr, _)) = transparent_receiver.map_or_else(|| let from_addrs = if let Some((addr, _)) = transparent_receiver.map_or_else(||
if account_receivers.len() > 1 { if account_receivers.len() > 1 {
Err(format_err!( Err(anyhow!(
"Account has more than one transparent receiver with funds to shield; this is not yet supported by the SDK. Provide a specific transparent receiver to shield funds from." "Account has more than one transparent receiver with funds to shield; this is not yet supported by the SDK. Provide a specific transparent receiver to shield funds from."
)) ))
} else { } else {
@ -1704,7 +1753,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_proposeSh
&from_addrs, &from_addrs,
min_confirmations, min_confirmations,
) )
.map_err(|e| format_err!("Error while shielding transaction: {}", e))?; .map_err(|e| anyhow!("Error while shielding transaction: {}", e))?;
Ok(utils::rust_bytes_to_java( Ok(utils::rust_bytes_to_java(
&env, &env,
@ -1741,7 +1790,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_createPro
let prover = LocalTxProver::new(Path::new(&spend_params), Path::new(&output_params)); let prover = LocalTxProver::new(Path::new(&spend_params), Path::new(&output_params));
let proposal = Proposal::decode(&env.convert_byte_array(proposal)?[..]) let proposal = Proposal::decode(&env.convert_byte_array(proposal)?[..])
.map_err(|e| format_err!("Invalid proposal: {}", e))? .map_err(|e| anyhow!("Invalid proposal: {}", e))?
.try_into_standard_proposal(&network, &db_data)?; .try_into_standard_proposal(&network, &db_data)?;
let txids = create_proposed_transactions::<_, _, Infallible, _, _>( let txids = create_proposed_transactions::<_, _, Infallible, _, _>(
@ -1753,7 +1802,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_createPro
OvkPolicy::Sender, OvkPolicy::Sender,
&proposal, &proposal,
) )
.map_err(|e| format_err!("Error while creating transactions: {}", e))?; .map_err(|e| anyhow!("Error while creating transactions: {}", e))?;
Ok(utils::rust_vec_to_java( Ok(utils::rust_vec_to_java(
env, env,
@ -1792,11 +1841,11 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_branchIdF
// Utility functions // Utility functions
// //
fn parse_network(value: u32) -> Result<Network, failure::Error> { fn parse_network(value: u32) -> anyhow::Result<Network> {
match value { match value {
0 => Ok(TestNetwork), 0 => Ok(TestNetwork),
1 => Ok(MainNetwork), 1 => Ok(MainNetwork),
_ => Err(format_err!("Invalid network type: {}. Expected either 0 or 1 for Testnet or Mainnet, respectively.", value)) _ => Err(anyhow!("Invalid network type: {}. Expected either 0 or 1 for Testnet or Mainnet, respectively.", value))
} }
} }
@ -1856,7 +1905,7 @@ pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_RustBackend_listTrans
)? )?
.into_raw()) .into_raw())
} }
Err(e) => Err(format_err!("Error while fetching address: {}", e)), Err(e) => Err(anyhow!("Error while fetching address: {}", e)),
} }
}); });
unwrap_exc_or(&mut env, res, ptr::null_mut()) unwrap_exc_or(&mut env, res, ptr::null_mut())

View File

@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use failure::Error;
use jni::JNIEnv; use jni::JNIEnv;
use std::any::Any; use std::any::Any;
use std::thread; use std::thread;
use tracing::error; use tracing::error;
type ExceptionResult<T> = thread::Result<Result<T, Error>>; type ExceptionResult<T> = thread::Result<anyhow::Result<T>>;
// Returns value or "throws" exception. `error_val` is returned, because exception will be thrown // Returns value or "throws" exception. `error_val` is returned, because exception will be thrown
// at the Java side. So this function should be used only for the `panic::catch_unwind` result. // at the Java side. So this function should be used only for the `panic::catch_unwind` result.

View File

@ -1,35 +1,35 @@
# 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.
org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.2.1=classpath org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.3.0=classpath
org.gradle.kotlin:gradle-kotlin-dsl-plugins:4.2.1=classpath org.gradle.kotlin:gradle-kotlin-dsl-plugins:4.3.0=classpath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=classpath org.jetbrains.intellij.deps:trove4j:1.0.20200330=classpath
org.jetbrains.kotlin:kotlin-android-extensions:1.9.20=classpath org.jetbrains.kotlin:kotlin-android-extensions:1.9.22=classpath
org.jetbrains.kotlin:kotlin-assignment:1.9.20=classpath org.jetbrains.kotlin:kotlin-assignment:1.9.22=classpath
org.jetbrains.kotlin:kotlin-build-tools-api:1.9.20=classpath org.jetbrains.kotlin:kotlin-build-tools-api:1.9.22=classpath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.20=classpath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.22=classpath
org.jetbrains.kotlin:kotlin-compiler-runner:1.9.20=classpath org.jetbrains.kotlin:kotlin-compiler-runner:1.9.22=classpath
org.jetbrains.kotlin:kotlin-daemon-client:1.9.20=classpath org.jetbrains.kotlin:kotlin-daemon-client:1.9.22=classpath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.20=classpath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22=classpath
org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.20=classpath org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.22=classpath
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.20=classpath org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.22=classpath
org.jetbrains.kotlin:kotlin-native-utils:1.9.20=classpath org.jetbrains.kotlin:kotlin-native-utils:1.9.22=classpath
org.jetbrains.kotlin:kotlin-project-model:1.9.20=classpath org.jetbrains.kotlin:kotlin-project-model:1.9.22=classpath
org.jetbrains.kotlin:kotlin-sam-with-receiver:1.9.20=classpath org.jetbrains.kotlin:kotlin-sam-with-receiver:1.9.22=classpath
org.jetbrains.kotlin:kotlin-scripting-common:1.9.20=classpath org.jetbrains.kotlin:kotlin-scripting-common:1.9.22=classpath
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.20=classpath org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.22=classpath
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.20=classpath org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.22=classpath
org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.20=classpath org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.22=classpath
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=classpath org.jetbrains.kotlin:kotlin-stdlib:1.9.22=classpath
org.jetbrains.kotlin:kotlin-tooling-core:1.9.20=classpath org.jetbrains.kotlin:kotlin-tooling-core:1.9.22=classpath
org.jetbrains.kotlin:kotlin-util-io:1.9.20=classpath org.jetbrains.kotlin:kotlin-util-io:1.9.22=classpath
org.jetbrains.kotlin:kotlin-util-klib:1.9.20=classpath org.jetbrains.kotlin:kotlin-util-klib:1.9.22=classpath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=classpath org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=classpath
org.jetbrains:annotations:13.0=classpath org.jetbrains:annotations:13.0=classpath
empty= empty=

View File

@ -1,66 +1,66 @@
# 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:8.1.1=runtimeClasspath androidx.databinding:databinding-common:8.3.0=runtimeClasspath
androidx.databinding:databinding-compiler-common:8.1.1=runtimeClasspath androidx.databinding:databinding-compiler-common:8.3.0=runtimeClasspath
com.android.databinding:baseLibrary:8.1.1=runtimeClasspath com.android.databinding:baseLibrary:8.3.0=runtimeClasspath
com.android.tools.analytics-library:crash:31.1.1=runtimeClasspath com.android.tools.analytics-library:crash:31.3.0=runtimeClasspath
com.android.tools.analytics-library:protos:31.1.1=runtimeClasspath com.android.tools.analytics-library:protos:31.3.0=runtimeClasspath
com.android.tools.analytics-library:shared:31.1.1=runtimeClasspath com.android.tools.analytics-library:shared:31.3.0=runtimeClasspath
com.android.tools.analytics-library:tracker:31.1.1=runtimeClasspath com.android.tools.analytics-library:tracker:31.3.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:8.1.1-10154469=runtimeClasspath com.android.tools.build:aapt2-proto:8.3.0-10880808=runtimeClasspath
com.android.tools.build:aaptcompiler:8.1.1=runtimeClasspath com.android.tools.build:aaptcompiler:8.3.0=runtimeClasspath
com.android.tools.build:apksig:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:apksig:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:apkzlib:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:apkzlib:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:builder-model:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:builder-model:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:builder-test-api:8.1.1=runtimeClasspath com.android.tools.build:builder-test-api:8.3.0=runtimeClasspath
com.android.tools.build:builder:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:builder:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:bundletool:1.14.0=runtimeClasspath com.android.tools.build:bundletool:1.15.6=runtimeClasspath
com.android.tools.build:gradle-api:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:gradle-api:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:gradle-settings-api:8.1.1=runtimeClasspath com.android.tools.build:gradle-settings-api:8.3.0=runtimeClasspath
com.android.tools.build:gradle:8.1.1=compileClasspath,runtimeClasspath com.android.tools.build:gradle:8.3.0=compileClasspath,runtimeClasspath
com.android.tools.build:manifest-merger:31.1.1=compileClasspath,runtimeClasspath com.android.tools.build:manifest-merger:31.3.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:31.1.1=runtimeClasspath com.android.tools.ddms:ddmlib:31.3.0=runtimeClasspath
com.android.tools.layoutlib:layoutlib-api:31.1.1=runtimeClasspath com.android.tools.layoutlib:layoutlib-api:31.3.0=runtimeClasspath
com.android.tools.lint:lint-model:31.1.1=runtimeClasspath com.android.tools.lint:lint-model:31.3.0=runtimeClasspath
com.android.tools.lint:lint-typedef-remover:31.1.1=runtimeClasspath com.android.tools.lint:lint-typedef-remover:31.3.0=runtimeClasspath
com.android.tools.utp:android-device-provider-ddmlib-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-device-provider-ddmlib-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-device-provider-gradle-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-device-provider-gradle-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-apk-installer-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-apk-installer-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-coverage-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-coverage-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-emulator-control-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-emulator-control-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-logcat-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-logcat-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-host-retention-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-host-retention-proto:31.3.0=runtimeClasspath
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:31.1.1=runtimeClasspath com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:31.3.0=runtimeClasspath
com.android.tools:annotations:31.1.1=runtimeClasspath com.android.tools:annotations:31.3.0=runtimeClasspath
com.android.tools:common:31.1.1=runtimeClasspath com.android.tools:common:31.3.0=runtimeClasspath
com.android.tools:dvlib:31.1.1=runtimeClasspath com.android.tools:dvlib:31.3.0=runtimeClasspath
com.android.tools:repository:31.1.1=runtimeClasspath com.android.tools:repository:31.3.0=runtimeClasspath
com.android.tools:sdk-common:31.1.1=runtimeClasspath com.android.tools:sdk-common:31.3.0=runtimeClasspath
com.android.tools:sdklib:31.1.1=runtimeClasspath com.android.tools:sdklib:31.3.0=runtimeClasspath
com.android:signflinger:8.1.1=runtimeClasspath com.android:signflinger:8.3.0=runtimeClasspath
com.android:zipflinger:8.1.1=compileClasspath,runtimeClasspath com.android:zipflinger:8.3.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.17.0=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.9=runtimeClasspath com.google.code.gson:gson:2.10.1=runtimeClasspath
com.google.crypto.tink:tink:1.7.0=runtimeClasspath com.google.crypto.tink:tink:1.7.0=runtimeClasspath
com.google.dagger:dagger:2.28.3=runtimeClasspath com.google.dagger:dagger:2.28.3=runtimeClasspath
com.google.errorprone:error_prone_annotations:2.11.0=runtimeClasspath com.google.errorprone:error_prone_annotations:2.18.0=runtimeClasspath
com.google.flatbuffers:flatbuffers-java:1.12.0=runtimeClasspath com.google.flatbuffers:flatbuffers-java:1.12.0=runtimeClasspath
com.google.guava:failureaccess:1.0.1=runtimeClasspath com.google.guava:failureaccess:1.0.1=runtimeClasspath
com.google.guava:guava:31.1-jre=runtimeClasspath com.google.guava:guava:32.0.1-jre=runtimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=runtimeClasspath com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=runtimeClasspath
com.google.j2objc:j2objc-annotations:1.3=runtimeClasspath com.google.j2objc:j2objc-annotations:2.8=runtimeClasspath
com.google.jimfs:jimfs:1.1=runtimeClasspath com.google.jimfs:jimfs:1.1=runtimeClasspath
com.google.protobuf:protobuf-java-util:3.19.3=runtimeClasspath com.google.protobuf:protobuf-java-util:3.22.3=runtimeClasspath
com.google.protobuf:protobuf-java:3.19.3=runtimeClasspath com.google.protobuf:protobuf-java:3.22.3=runtimeClasspath
com.google.testing.platform:core-proto:0.0.8-alpha08=runtimeClasspath com.google.testing.platform:core-proto:0.0.9-alpha02=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
@ -69,28 +69,28 @@ com.sun.istack:istack-commons-runtime:3.0.8=runtimeClasspath
com.sun.xml.fastinfoset:FastInfoset:1.2.16=runtimeClasspath com.sun.xml.fastinfoset:FastInfoset:1.2.16=runtimeClasspath
com.vdurmont:semver4j:3.1.0=runtimeClasspath com.vdurmont:semver4j:3.1.0=runtimeClasspath
commons-codec:commons-codec:1.11=runtimeClasspath commons-codec:commons-codec:1.11=runtimeClasspath
commons-io:commons-io:2.12.0=runtimeClasspath commons-io:commons-io:2.15.1=runtimeClasspath
commons-logging:commons-logging:1.2=runtimeClasspath commons-logging:commons-logging:1.2=runtimeClasspath
io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.0=compileClasspath,runtimeClasspath io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.6=compileClasspath,runtimeClasspath
io.grpc:grpc-api:1.45.1=runtimeClasspath io.grpc:grpc-api:1.57.0=runtimeClasspath
io.grpc:grpc-context:1.45.1=runtimeClasspath io.grpc:grpc-context:1.57.0=runtimeClasspath
io.grpc:grpc-core:1.45.1=runtimeClasspath io.grpc:grpc-core:1.57.0=runtimeClasspath
io.grpc:grpc-netty:1.45.1=runtimeClasspath io.grpc:grpc-netty:1.57.0=runtimeClasspath
io.grpc:grpc-protobuf-lite:1.45.1=runtimeClasspath io.grpc:grpc-protobuf-lite:1.57.0=runtimeClasspath
io.grpc:grpc-protobuf:1.45.1=runtimeClasspath io.grpc:grpc-protobuf:1.57.0=runtimeClasspath
io.grpc:grpc-stub:1.45.1=runtimeClasspath io.grpc:grpc-stub:1.57.0=runtimeClasspath
io.netty:netty-buffer:4.1.72.Final=runtimeClasspath io.netty:netty-buffer:4.1.93.Final=runtimeClasspath
io.netty:netty-codec-http2:4.1.72.Final=runtimeClasspath io.netty:netty-codec-http2:4.1.93.Final=runtimeClasspath
io.netty:netty-codec-http:4.1.72.Final=runtimeClasspath io.netty:netty-codec-http:4.1.93.Final=runtimeClasspath
io.netty:netty-codec-socks:4.1.72.Final=runtimeClasspath io.netty:netty-codec-socks:4.1.93.Final=runtimeClasspath
io.netty:netty-codec:4.1.72.Final=runtimeClasspath io.netty:netty-codec:4.1.93.Final=runtimeClasspath
io.netty:netty-common:4.1.72.Final=runtimeClasspath io.netty:netty-common:4.1.93.Final=runtimeClasspath
io.netty:netty-handler-proxy:4.1.72.Final=runtimeClasspath io.netty:netty-handler-proxy:4.1.93.Final=runtimeClasspath
io.netty:netty-handler:4.1.72.Final=runtimeClasspath io.netty:netty-handler:4.1.93.Final=runtimeClasspath
io.netty:netty-resolver:4.1.72.Final=runtimeClasspath io.netty:netty-resolver:4.1.93.Final=runtimeClasspath
io.netty:netty-tcnative-classes:2.0.46.Final=runtimeClasspath io.netty:netty-transport-native-unix-common:4.1.93.Final=runtimeClasspath
io.netty:netty-transport:4.1.72.Final=runtimeClasspath io.netty:netty-transport:4.1.93.Final=runtimeClasspath
io.perfmark:perfmark-api:0.23.0=runtimeClasspath io.perfmark:perfmark-api:0.26.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
@ -100,75 +100,73 @@ net.java.dev.jna:jna:5.6.0=runtimeClasspath
net.sf.jopt-simple:jopt-simple:4.9=runtimeClasspath net.sf.jopt-simple:jopt-simple:4.9=runtimeClasspath
net.sf.kxml:kxml2:2.3.0=runtimeClasspath net.sf.kxml:kxml2:2.3.0=runtimeClasspath
org.apache.commons:commons-compress:1.21=runtimeClasspath org.apache.commons:commons-compress:1.21=runtimeClasspath
org.apache.httpcomponents:httpclient:4.5.13=runtimeClasspath org.apache.httpcomponents:httpclient:4.5.14=runtimeClasspath
org.apache.httpcomponents:httpcore:4.4.15=runtimeClasspath org.apache.httpcomponents:httpcore:4.4.16=runtimeClasspath
org.apache.httpcomponents:httpmime:4.5.6=runtimeClasspath org.apache.httpcomponents:httpmime:4.5.6=runtimeClasspath
org.bitbucket.b_c:jose4j:0.7.0=runtimeClasspath org.bitbucket.b_c:jose4j:0.7.0=runtimeClasspath
org.bouncycastle:bcpkix-jdk15on:1.67=runtimeClasspath org.bouncycastle:bcpkix-jdk15on:1.67=runtimeClasspath
org.bouncycastle:bcprov-jdk15on:1.67=runtimeClasspath org.bouncycastle:bcprov-jdk15on:1.67=runtimeClasspath
org.checkerframework:checker-qual:3.12.0=runtimeClasspath org.checkerframework:checker-qual:3.33.0=runtimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.19=runtimeClasspath org.codehaus.mojo:animal-sniffer-annotations:1.23=runtimeClasspath
org.glassfish.jaxb:jaxb-runtime:2.3.2=runtimeClasspath 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.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-android-extensions:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-assignment-compiler-plugin-embeddable:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-assignment-compiler-plugin-embeddable:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-build-tools-api:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-build-tools-api:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.20=kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.22=kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-compiler-runner:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-daemon-client:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-daemon-client:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.20=kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.22=kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-native-utils:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-native-utils:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-project-model:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-project-model:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinCompilerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC2=runtimeClasspath org.jetbrains.kotlin:kotlin-reflect:1.9.20=runtimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.9.20=compileClasspath org.jetbrains.kotlin:kotlin-reflect:1.9.22=compileClasspath
org.jetbrains.kotlin:kotlin-sam-with-receiver-compiler-plugin-embeddable:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-sam-with-receiver-compiler-plugin-embeddable:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-script-runtime:1.9.20=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-script-runtime:1.9.22=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-common:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-common:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-common:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-common:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.20=kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.22=kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.21=runtimeClasspath org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.23=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.20-RC2=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20-RC2=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20-RC2=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib:1.9.20=runtimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.8.20-RC2=runtimeClasspath org.jetbrains.kotlin:kotlin-stdlib:1.9.22=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=compileClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain org.jetbrains.kotlin:kotlin-tooling-core:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-tooling-core:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-util-io:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-util-io:1.9.21=compileClasspath,runtimeClasspath org.jetbrains.kotlin:kotlin-util-klib:1.9.23=compileClasspath,runtimeClasspath
org.jetbrains.kotlin:kotlin-util-klib:1.9.21=compileClasspath,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
org.json:json:20230227=runtimeClasspath org.jetbrains:annotations:23.0.0=runtimeClasspath
org.json:json:20240205=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.2=runtimeClasspath org.ow2.asm:asm-analysis:9.6=runtimeClasspath
org.ow2.asm:asm-commons:9.2=runtimeClasspath org.ow2.asm:asm-commons:9.6=runtimeClasspath
org.ow2.asm:asm-tree:9.2=runtimeClasspath org.ow2.asm:asm-tree:9.6=runtimeClasspath
org.ow2.asm:asm-util:9.2=runtimeClasspath org.ow2.asm:asm-util:9.6=runtimeClasspath
org.ow2.asm:asm:9.2=compileClasspath,runtimeClasspath org.ow2.asm:asm:9.6=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-compat-6-1:0.12.2=runtimeClasspath wtf.emulator:gradle-compat-6-1:0.16.2=runtimeClasspath
wtf.emulator:gradle-compat-6-6:0.12.2=runtimeClasspath wtf.emulator:gradle-compat-6-6:0.16.2=runtimeClasspath
wtf.emulator:gradle-compat-7-6:0.12.2=runtimeClasspath wtf.emulator:gradle-compat-7-6:0.16.2=runtimeClasspath
wtf.emulator:gradle-compat-api:0.12.2=runtimeClasspath wtf.emulator:gradle-compat-api:0.16.2=runtimeClasspath
wtf.emulator:gradle-compat:0.12.2=runtimeClasspath wtf.emulator:gradle-compat:0.16.2=runtimeClasspath
wtf.emulator:gradle-plugin:0.12.2=compileClasspath,runtimeClasspath wtf.emulator:gradle-plugin:0.16.2=compileClasspath,runtimeClasspath
xerces:xercesImpl:2.12.0=runtimeClasspath
xml-apis:xml-apis:1.4.01=runtimeClasspath
empty=annotationProcessor,kotlinScriptDefExtensions empty=annotationProcessor,kotlinScriptDefExtensions

View File

@ -176,7 +176,7 @@ fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
) )
} }
if (this is CommonExtension<*, *, *, *, *>) { if (this is CommonExtension<*, *, *, *, *, *>) {
kotlinOptions { kotlinOptions {
jvmTarget = project.property("ANDROID_JVM_TARGET").toString() jvmTarget = project.property("ANDROID_JVM_TARGET").toString()
allWarningsAsErrors = project.property("ZCASH_IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean() allWarningsAsErrors = project.property("ZCASH_IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
@ -185,6 +185,6 @@ fun com.android.build.gradle.BaseExtension.configureBaseExtension() {
} }
} }
fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) {
(this as ExtensionAware).extensions.configure("kotlinOptions", block) (this as ExtensionAware).extensions.configure("kotlinOptions", block)
} }

View File

@ -66,9 +66,16 @@ class MainActivity :
appBarConfiguration = appBarConfiguration =
AppBarConfiguration( AppBarConfiguration(
setOf( setOf(
R.id.nav_home, R.id.nav_address, R.id.nav_balance, R.id.nav_block, R.id.nav_private_key, R.id.nav_home,
R.id.nav_latest_height, R.id.nav_block_range, R.id.nav_address,
R.id.nav_transactions, R.id.nav_utxos, R.id.nav_send R.id.nav_balance,
R.id.nav_block,
R.id.nav_private_key,
R.id.nav_latest_height,
R.id.nav_block_range,
R.id.nav_transactions,
R.id.nav_utxos,
R.id.nav_send
), ),
drawerLayout drawerLayout
) )

View File

@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@ -84,7 +84,7 @@ private fun AddressesTopAppBar(onBack: () -> Unit) {
onClick = onBack onClick = onBack
) { ) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null contentDescription = null
) )
} }

View File

@ -7,7 +7,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Autorenew import androidx.compose.material.icons.outlined.Autorenew
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@ -82,7 +82,7 @@ private fun BalanceTopAppBar(
onClick = onBack onClick = onBack
) { ) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null contentDescription = null
) )
} }

View File

@ -14,7 +14,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -104,7 +104,7 @@ private fun SendTopAppBar(onBack: () -> Unit) {
onClick = onBack onClick = onBack
) { ) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null contentDescription = null
) )
} }

View File

@ -15,7 +15,7 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -112,7 +112,7 @@ private fun ServerTopAppBar(onBack: () -> Unit) {
onClick = onBack onClick = onBack
) { ) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null contentDescription = null
) )
} }

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.Autorenew import androidx.compose.material.icons.outlined.Autorenew
import androidx.compose.material3.Button import androidx.compose.material3.Button
@ -97,7 +98,7 @@ private fun TransactionsTopAppBar(
onClick = onBack onClick = onBack
) { ) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null contentDescription = null
) )
} }

View File

@ -26,7 +26,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=2.1.0 LIBRARY_VERSION=2.1.1
# 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
@ -83,66 +83,64 @@ ANDROID_COMPILE_SDK_VERSION=34
# - Clang major version in backend-lib/build.rs # - Clang major version in backend-lib/build.rs
ANDROID_NDK_VERSION=26.1.10909125 ANDROID_NDK_VERSION=26.1.10909125
ANDROID_GRADLE_PLUGIN_VERSION=8.1.1 ANDROID_GRADLE_PLUGIN_VERSION=8.3.0
DETEKT_VERSION=1.23.0 DETEKT_VERSION=1.23.6
DETEKT_COMPOSE_RULES_VERSION=0.3.5 DETEKT_COMPOSE_RULES_VERSION=0.3.15
DOKKA_VERSION=1.9.10 DOKKA_VERSION=1.9.20
EMULATOR_WTF_GRADLE_PLUGIN_VERSION=0.12.2 EMULATOR_WTF_GRADLE_PLUGIN_VERSION=0.16.2
FLANK_VERSION=23.10.1 FLANK_VERSION=23.10.1
# When changing this, be sure to change build-conventions/gradle.properties#FOOJAY_TOOLCHAIN_RESOLVER_VERSION too # When changing this, be sure to change build-conventions/gradle.properties#FOOJAY_TOOLCHAIN_RESOLVER_VERSION too
FOOJAY_TOOLCHAIN_RESOLVER_VERSION=0.5.0 FOOJAY_TOOLCHAIN_RESOLVER_VERSION=0.8.0
FULLADLE_VERSION=0.17.4 FULLADLE_VERSION=0.17.4
GRADLE_VERSIONS_PLUGIN_VERSION=0.51.0 GRADLE_VERSIONS_PLUGIN_VERSION=0.51.0
KSP_VERSION=1.8.20-1.0.10 KSP_VERSION=1.9.23-1.0.20
KTLINT_VERSION=1.1.0 KTLINT_VERSION=1.2.1
PROTOBUF_GRADLE_PLUGIN_VERSION=0.9.4 PROTOBUF_GRADLE_PLUGIN_VERSION=0.9.4
RUST_GRADLE_PLUGIN_VERSION=0.9.3 RUST_GRADLE_PLUGIN_VERSION=0.9.3
ANDROIDX_ACTIVITY_VERSION=1.8.1 ANDROIDX_ACTIVITY_VERSION=1.8.2
ANDROIDX_ANNOTATION_VERSION=1.7.0 ANDROIDX_ANNOTATION_VERSION=1.7.1
ANDROIDX_APPCOMPAT_VERSION=1.6.1 ANDROIDX_APPCOMPAT_VERSION=1.6.1
ANDROIDX_COMPOSE_COMPILER_VERSION=1.5.7 ANDROIDX_COMPOSE_COMPILER_VERSION=1.5.11
ANDROIDX_COMPOSE_MATERIAL3_VERSION=1.1.1 ANDROIDX_COMPOSE_MATERIAL3_VERSION=1.2.1
ANDROIDX_COMPOSE_VERSION=1.6.2 ANDROIDX_COMPOSE_VERSION=1.6.5
ANDROIDX_COMPOSE_MATERIAL_ICONS_VERSION=1.5.4 ANDROIDX_COMPOSE_MATERIAL_ICONS_VERSION=1.6.5
ANDROIDX_CONSTRAINT_LAYOUT_VERSION=2.1.4 ANDROIDX_CONSTRAINT_LAYOUT_VERSION=2.1.4
ANDROIDX_CORE_VERSION=1.12.0 ANDROIDX_CORE_VERSION=1.12.0
ANDROIDX_DATABASE_VERSION=2.4.0 ANDROIDX_DATABASE_VERSION=2.4.0
ANDROIDX_ESPRESSO_VERSION=3.5.1 ANDROIDX_ESPRESSO_VERSION=3.5.1
ANDROIDX_LIFECYCLE_VERSION=2.6.2 ANDROIDX_LIFECYCLE_VERSION=2.7.0
ANDROIDX_MULTIDEX_VERSION=2.0.1 ANDROIDX_MULTIDEX_VERSION=2.0.1
ANDROIDX_NAVIGATION_VERSION=2.7.5 ANDROIDX_NAVIGATION_VERSION=2.7.7
ANDROIDX_NAVIGATION_COMPOSE_VERSION=2.7.5 ANDROIDX_NAVIGATION_COMPOSE_VERSION=2.7.7
ANDROIDX_NAVIGATION_FRAGMENT_VERSION=2.7.5 ANDROIDX_NAVIGATION_FRAGMENT_VERSION=2.7.7
ANDROIDX_PROFILE_INSTALLER_VERSION=1.3.1 ANDROIDX_PROFILE_INSTALLER_VERSION=1.3.1
ANDROIDX_ROOM_VERSION=2.5.1
ANDROIDX_SECURITY_CRYPTO_VERSION=1.1.0-alpha06 ANDROIDX_SECURITY_CRYPTO_VERSION=1.1.0-alpha06
ANDROIDX_TEST_JUNIT_VERSION=1.1.5 ANDROIDX_TEST_JUNIT_VERSION=1.1.5
ANDROIDX_TEST_MACROBENCHMARK_VERSION=1.2.2 ANDROIDX_TEST_MACROBENCHMARK_VERSION=1.2.3
ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.4.2 ANDROIDX_TEST_ORCHESTRATOR_VERSION=1.4.2
ANDROIDX_TEST_CORE_VERSION=1.5.0 ANDROIDX_TEST_CORE_VERSION=1.5.0
ANDROIDX_TEST_RUNNER_VERSION=1.5.2 ANDROIDX_TEST_RUNNER_VERSION=1.5.2
ANDROIDX_TRACING_VERSION=1.3.0-alpha02 ANDROIDX_TRACING_VERSION=1.3.0-alpha02
ANDROIDX_UI_AUTOMATOR_VERSION=2.3.0-alpha05 ANDROIDX_UI_AUTOMATOR_VERSION=2.3.0
BIP39_VERSION=1.0.7
CORE_LIBRARY_DESUGARING_VERSION=2.0.4 CORE_LIBRARY_DESUGARING_VERSION=2.0.4
COROUTINES_OKHTTP=1.0 GOOGLE_MATERIAL_VERSION=1.11.0
GOOGLE_MATERIAL_VERSION=1.9.0
GRPC_KOTLIN_VERSION=1.4.1 GRPC_KOTLIN_VERSION=1.4.1
GRPC_VERSION=1.60.0 GRPC_VERSION=1.63.0
GSON_VERSION=2.9.0 GSON_VERSION=2.10.1
JACOCO_VERSION=0.8.9 JACOCO_VERSION=0.8.12
JAVAX_ANNOTATION_VERSION=1.3.2 JAVAX_ANNOTATION_VERSION=1.3.2
JUNIT_VERSION=5.9.3 JUNIT_VERSION=5.10.2
KOTLINX_COROUTINES_VERSION=1.7.3 KOTLINX_COROUTINES_VERSION=1.8.0
KOTLINX_DATETIME_VERSION=0.5.0 KOTLINX_DATETIME_VERSION=0.5.0
KOTLINX_IMMUTABLE_COLLECTIONS_VERSION=0.3.6 KOTLINX_IMMUTABLE_COLLECTIONS_VERSION=0.3.7
KOTLIN_VERSION=1.9.21 KOTLIN_VERSION=1.9.23
MOCKITO_KOTLIN_VERSION=2.2.0 MOCKITO_VERSION=5.11.0
MOCKITO_VERSION=5.8.0 PROTOC_VERSION=4.26.1
PROTOC_VERSION=3.25.1
ZCASH_WALLET_PLUGINS_VERSION=1.0.1 ZCASH_WALLET_PLUGINS_VERSION=1.0.1
BIP39_VERSION=1.0.8
# This shouldn't be changed, as Android doesn't support targets beyond Java 8 # This shouldn't be changed, as Android doesn't support targets beyond Java 8
ANDROID_JVM_TARGET=1.8 ANDROID_JVM_TARGET=1.8

Binary file not shown.

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026 distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

20
gradlew.bat vendored
View File

@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail

View File

@ -129,7 +129,6 @@ dependencies {
androidTestImplementation(libs.androidx.test.runner) androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.junit) androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.core) androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.coroutines.okhttp)
androidTestImplementation(libs.kotlin.test) androidTestImplementation(libs.kotlin.test)
} }

View File

@ -16,7 +16,6 @@ internal class AndroidChannelFactory(context: android.content.Context) : Channel
return AndroidChannelBuilder return AndroidChannelBuilder
.forAddress(endpoint.host, endpoint.port) .forAddress(endpoint.host, endpoint.port)
.context(context) .context(context)
.enableFullStreamDecompression()
.apply { .apply {
if (endpoint.isSecure) { if (endpoint.isSecure) {
useTransportSecurity() useTransportSecurity()

View File

@ -1,5 +1,5 @@
[toolchain] [toolchain]
channel = "1.75.0" channel = "1.77.2"
targets = [ targets = [
"armv7-linux-androideabi", "armv7-linux-androideabi",
"aarch64-linux-android", "aarch64-linux-android",

View File

@ -122,12 +122,10 @@ dependencies {
// was buggy, crashing in several places. It also would require a separate test flavor because it's minimum API 26 // was buggy, crashing in several places. It also would require a separate test flavor because it's minimum API 26
// because "JUnit 5 uses Java 8-specific APIs that didn't exist on Android before the Oreo release." // because "JUnit 5 uses Java 8-specific APIs that didn't exist on Android before the Oreo release."
androidTestImplementation(libs.androidx.multidex) androidTestImplementation(libs.androidx.multidex)
androidTestImplementation(libs.mockito.kotlin)
androidTestImplementation(libs.mockito.android) androidTestImplementation(libs.mockito.android)
androidTestImplementation(libs.androidx.test.runner) androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.junit) androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.core) androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.coroutines.okhttp)
androidTestImplementation(libs.kotlin.test) androidTestImplementation(libs.kotlin.test)
androidTestImplementation(libs.kotlinx.coroutines.test) androidTestImplementation(libs.kotlinx.coroutines.test)

View File

@ -0,0 +1,9 @@
# Strip out log messages
-assumenosideeffects public class cash.z.ecc.android.sdk.internal.Twig {
public static *** verbose(...);
public static *** debug(...);
public static *** info(...);
public static *** warn(...);
public static *** error(...);
public static *** assertLoggingStripped();
}

View File

@ -150,6 +150,7 @@ internal class FakeRustBackend(
override suspend fun getMemoAsUtf8( override suspend fun getMemoAsUtf8(
txId: ByteArray, txId: ByteArray,
protocol: Int,
outputIndex: Int outputIndex: Int
): String? = error("Intentionally not implemented in mocked FakeRustBackend implementation.") ): String? = error("Intentionally not implemented in mocked FakeRustBackend implementation.")

View File

@ -327,17 +327,25 @@ class SdkSynchronizer private constructor(
} }
override fun getMemos(transactionOverview: TransactionOverview): Flow<String> { override fun getMemos(transactionOverview: TransactionOverview): Flow<String> {
return storage.getSaplingOutputIndices(transactionOverview.rawId).map { return storage.getOutputProperties(transactionOverview.rawId).map { properties ->
runCatching { if (!properties.protocol.isShielded()) {
backend.getMemoAsUtf8(transactionOverview.rawId.byteArray, it) ""
}.onFailure { } else {
Twig.error { "Failed to get memo with: $it" } runCatching {
}.onSuccess { backend.getMemoAsUtf8(
Twig.debug { "Transaction memo queried: $it" } txId = transactionOverview.rawId.byteArray,
}.fold( protocol = properties.protocol,
onSuccess = { it ?: "" }, outputIndex = properties.index
onFailure = { "" } )
) }.onFailure {
Twig.error { "Failed to get memo with: $it" }
}.onSuccess {
Twig.debug { "Transaction memo queried: $it" }
}.fold(
onSuccess = { it ?: "" },
onFailure = { "" }
)
}
} }
} }
@ -555,6 +563,19 @@ class SdkSynchronizer private constructor(
account account
) )
/**
* Creates a proposal for fulfilling a payment ZIP-321 URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI String
*
* @return the proposal or an exception
*/
@Throws(TransactionEncoderException::class)
override suspend fun proposeFulfillingPaymentUri(
account: Account,
uri: String
): Proposal = txManager.proposeTransferFromUri(account, uri)
@Throws(TransactionEncoderException::class) @Throws(TransactionEncoderException::class)
override suspend fun proposeTransfer( override suspend fun proposeTransfer(
account: Account, account: Account,

View File

@ -186,6 +186,19 @@ interface Synchronizer {
memo: String = "" memo: String = ""
): Proposal ): Proposal
/**
* Creates a proposal for fulfilling a payment ZIP-321 URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI String
*
* @return the proposal or an exception
*/
suspend fun proposeFulfillingPaymentUri(
account: Account,
uri: String
): Proposal
/** /**
* Creates a proposal for shielding any transparent funds received by the given account. * Creates a proposal for shielding any transparent funds received by the given account.
* *

View File

@ -7,6 +7,7 @@ import cash.z.ecc.android.sdk.internal.model.ScanSummary
import cash.z.ecc.android.sdk.internal.model.SubtreeRoot import cash.z.ecc.android.sdk.internal.model.SubtreeRoot
import cash.z.ecc.android.sdk.internal.model.TreeState import cash.z.ecc.android.sdk.internal.model.TreeState
import cash.z.ecc.android.sdk.internal.model.WalletSummary import cash.z.ecc.android.sdk.internal.model.WalletSummary
import cash.z.ecc.android.sdk.internal.model.ZcashProtocol
import cash.z.ecc.android.sdk.model.Account import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.BlockHeight import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray import cash.z.ecc.android.sdk.model.FirstClassByteArray
@ -25,6 +26,11 @@ internal interface TypesafeBackend {
recoverUntil: BlockHeight? recoverUntil: BlockHeight?
): UnifiedSpendingKey ): UnifiedSpendingKey
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
@Suppress("LongParameterList") @Suppress("LongParameterList")
suspend fun proposeTransfer( suspend fun proposeTransfer(
account: Account, account: Account,
@ -75,6 +81,7 @@ internal interface TypesafeBackend {
suspend fun getMemoAsUtf8( suspend fun getMemoAsUtf8(
txId: ByteArray, txId: ByteArray,
protocol: ZcashProtocol,
outputIndex: Int outputIndex: Int
): String? ): String?

View File

@ -8,6 +8,7 @@ import cash.z.ecc.android.sdk.internal.model.ScanSummary
import cash.z.ecc.android.sdk.internal.model.SubtreeRoot import cash.z.ecc.android.sdk.internal.model.SubtreeRoot
import cash.z.ecc.android.sdk.internal.model.TreeState import cash.z.ecc.android.sdk.internal.model.TreeState
import cash.z.ecc.android.sdk.internal.model.WalletSummary import cash.z.ecc.android.sdk.internal.model.WalletSummary
import cash.z.ecc.android.sdk.internal.model.ZcashProtocol
import cash.z.ecc.android.sdk.model.Account import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.BlockHeight import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray import cash.z.ecc.android.sdk.model.FirstClassByteArray
@ -36,6 +37,17 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke
) )
} }
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal =
Proposal.fromUnsafe(
backend.proposeTransferFromUri(
account.value,
uri
)
)
@Suppress("LongParameterList") @Suppress("LongParameterList")
override suspend fun proposeTransfer( override suspend fun proposeTransfer(
account: Account, account: Account,
@ -147,8 +159,14 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke
override suspend fun getMemoAsUtf8( override suspend fun getMemoAsUtf8(
txId: ByteArray, txId: ByteArray,
protocol: ZcashProtocol,
outputIndex: Int outputIndex: Int
): String? = backend.getMemoAsUtf8(txId, outputIndex) ): String? =
backend.getMemoAsUtf8(
txId = txId,
protocol = protocol.poolCode,
outputIndex = outputIndex
)
override suspend fun initDataDb(seed: ByteArray?) { override suspend fun initDataDb(seed: ByteArray?) {
val ret = backend.initDataDb(seed) val ret = backend.initDataDb(seed)

View File

@ -5,14 +5,13 @@ package cash.z.ecc.android.sdk.internal.db
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.SupportSQLiteQueryBuilder import androidx.sqlite.db.SupportSQLiteQueryBuilder
import kotlinx.coroutines.Dispatchers import cash.z.ecc.android.sdk.internal.SdkDispatchers
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import java.util.Locale import java.util.Locale
import kotlin.coroutines.CoroutineContext
/** /**
* Performs a query on a background thread. * Performs a query on a background thread using the dedicated [SdkDispatchers.DATABASE_IO] dispatcher.
* *
* Note that this method is best for small queries, as Cursor has an in-memory window of cached data. If iterating * Note that this method is best for small queries, as Cursor has an in-memory window of cached data. If iterating
* through a large number of items that exceeds the window, the Cursor may perform additional IO. * through a large number of items that exceeds the window, the Cursor may perform additional IO.
@ -28,7 +27,6 @@ internal fun <T> SQLiteDatabase.queryAndMap(
orderBy: String? = null, orderBy: String? = null,
limit: String? = null, limit: String? = null,
offset: String? = null, offset: String? = null,
coroutineContext: CoroutineContext = Dispatchers.IO,
cursorParser: CursorParser<T> cursorParser: CursorParser<T>
) = flow<T> { ) = flow<T> {
// TODO [#703]: Support blobs for argument binding // TODO [#703]: Support blobs for argument binding
@ -64,10 +62,10 @@ internal fun <T> SQLiteDatabase.queryAndMap(
emit(cursorParser.newObject(it)) emit(cursorParser.newObject(it))
} }
} }
}.flowOn(coroutineContext) }.flowOn(SdkDispatchers.DATABASE_IO)
/** /**
* Performs a query on a background thread. * Performs a query on a background thread using the dedicated [SdkDispatchers.DATABASE_IO] dispatcher.
* *
* Note that this method is best for small queries, as Cursor has an in-memory window of cached data. If iterating * Note that this method is best for small queries, as Cursor has an in-memory window of cached data. If iterating
* through a large number of items that exceeds the window, the Cursor may perform additional IO. * through a large number of items that exceeds the window, the Cursor may perform additional IO.
@ -83,7 +81,6 @@ internal fun <T> SupportSQLiteDatabase.queryAndMap(
orderBy: String? = null, orderBy: String? = null,
limit: String? = null, limit: String? = null,
offset: String? = null, offset: String? = null,
coroutineContext: CoroutineContext = Dispatchers.IO,
cursorParser: CursorParser<T> cursorParser: CursorParser<T>
) = flow<T> { ) = flow<T> {
val qb = val qb =
@ -111,4 +108,4 @@ internal fun <T> SupportSQLiteDatabase.queryAndMap(
emit(cursorParser.newObject(it)) emit(cursorParser.newObject(it))
} }
} }
}.flowOn(coroutineContext) }.flowOn(SdkDispatchers.DATABASE_IO)

View File

@ -53,8 +53,9 @@ internal class DbDerivedDataRepository(
override val allTransactions: Flow<List<DbTransactionOverview>> override val allTransactions: Flow<List<DbTransactionOverview>>
get() = invalidatingFlow.map { derivedDataDb.allTransactionView.getAllTransactions().toList() } get() = invalidatingFlow.map { derivedDataDb.allTransactionView.getAllTransactions().toList() }
override fun getSaplingOutputIndices(transactionId: FirstClassByteArray) = override fun getOutputProperties(transactionId: FirstClassByteArray) =
derivedDataDb.txOutputsView.getSaplingOutputIndices(transactionId) derivedDataDb.txOutputsView
.getOutputProperties(transactionId)
override fun getRecipients(transactionId: FirstClassByteArray): Flow<TransactionRecipient> { override fun getRecipients(transactionId: FirstClassByteArray): Flow<TransactionRecipient> {
return derivedDataDb.txOutputsView.getRecipients(transactionId) return derivedDataDb.txOutputsView.getRecipients(transactionId)

View File

@ -6,10 +6,8 @@ import cash.z.ecc.android.sdk.internal.model.EncodedTransaction
import cash.z.ecc.android.sdk.model.BlockHeight import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.ZcashNetwork import cash.z.ecc.android.sdk.model.ZcashNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
import java.util.Locale import java.util.Locale
internal class TransactionTable( internal class TransactionTable(
@ -57,13 +55,11 @@ internal class TransactionTable(
} }
suspend fun count() = suspend fun count() =
withContext(Dispatchers.IO) { sqliteDatabase.queryAndMap(
sqliteDatabase.queryAndMap( table = TransactionTableDefinition.TABLE_NAME,
table = TransactionTableDefinition.TABLE_NAME, columns = PROJECTION_COUNT,
columns = PROJECTION_COUNT, cursorParser = { it.getLong(0) }
cursorParser = { it.getLong(0) } ).first()
).first()
}
suspend fun countUnmined() = suspend fun countUnmined() =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(

View File

@ -2,6 +2,7 @@ package cash.z.ecc.android.sdk.internal.db.derived
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import cash.z.ecc.android.sdk.internal.db.queryAndMap import cash.z.ecc.android.sdk.internal.db.queryAndMap
import cash.z.ecc.android.sdk.internal.model.OutputProperties
import cash.z.ecc.android.sdk.model.Account import cash.z.ecc.android.sdk.model.Account
import cash.z.ecc.android.sdk.model.FirstClassByteArray import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.TransactionRecipient import cash.z.ecc.android.sdk.model.TransactionRecipient
@ -22,7 +23,11 @@ internal class TxOutputsView(
TxOutputsViewDefinition.COLUMN_BLOB_TRANSACTION_ID TxOutputsViewDefinition.COLUMN_BLOB_TRANSACTION_ID
) )
private val PROJECTION_OUTPUT_INDEX = arrayOf(TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_INDEX) private val PROJECTION_OUTPUT_PROPERTIES =
arrayOf(
TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_INDEX,
TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_POOL,
)
private val PROJECTION_RECIPIENT = private val PROJECTION_RECIPIENT =
arrayOf( arrayOf(
@ -40,17 +45,22 @@ internal class TxOutputsView(
) )
} }
fun getSaplingOutputIndices(transactionId: FirstClassByteArray) = fun getOutputProperties(transactionId: FirstClassByteArray) =
sqliteDatabase.queryAndMap( sqliteDatabase.queryAndMap(
table = TxOutputsViewDefinition.VIEW_NAME, table = TxOutputsViewDefinition.VIEW_NAME,
columns = PROJECTION_OUTPUT_INDEX, columns = PROJECTION_OUTPUT_PROPERTIES,
selection = SELECT_BY_TRANSACTION_ID_AND_NOT_CHANGE, selection = SELECT_BY_TRANSACTION_ID_AND_NOT_CHANGE,
selectionArgs = arrayOf(transactionId.byteArray), selectionArgs = arrayOf(transactionId.byteArray),
orderBy = ORDER_BY, orderBy = ORDER_BY,
cursorParser = { cursorParser = {
val idColumnOutputIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_INDEX) val idColumnOutputIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_INDEX)
val idColumnOutputPoolIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_INTEGER_OUTPUT_POOL)
it.getInt(idColumnOutputIndex) OutputProperties.new(
index = it.getInt(idColumnOutputIndex),
// Converting blob to Int
poolType = it.getInt(idColumnOutputPoolIndex)
)
} }
) )

View File

@ -0,0 +1,25 @@
package cash.z.ecc.android.sdk.internal.model
/**
* Typesafe model class representing different properties from [TxOutputsView]
*/
internal class OutputProperties(
val index: Int,
val protocol: ZcashProtocol
) {
companion object {
fun new(
index: Int,
poolType: Int
): OutputProperties {
require(index >= 0) { "Output index: $index must be greater or equal to zero" }
require(ZcashProtocol.validate(poolType)) { "Output poolType: $poolType unknown" }
return OutputProperties(
index = index,
protocol = ZcashProtocol.fromPoolType(poolType)
)
}
}
}

View File

@ -2,6 +2,7 @@ package cash.z.ecc.android.sdk.internal.repository
import cash.z.ecc.android.sdk.internal.model.DbTransactionOverview import cash.z.ecc.android.sdk.internal.model.DbTransactionOverview
import cash.z.ecc.android.sdk.internal.model.EncodedTransaction import cash.z.ecc.android.sdk.internal.model.EncodedTransaction
import cash.z.ecc.android.sdk.internal.model.OutputProperties
import cash.z.ecc.android.sdk.model.BlockHeight import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.FirstClassByteArray import cash.z.ecc.android.sdk.model.FirstClassByteArray
import cash.z.ecc.android.sdk.model.TransactionRecipient import cash.z.ecc.android.sdk.model.TransactionRecipient
@ -81,7 +82,7 @@ internal interface DerivedDataRepository {
val allTransactions: Flow<List<DbTransactionOverview>> val allTransactions: Flow<List<DbTransactionOverview>>
fun getSaplingOutputIndices(transactionId: FirstClassByteArray): Flow<Int> fun getOutputProperties(transactionId: FirstClassByteArray): Flow<OutputProperties>
fun getRecipients(transactionId: FirstClassByteArray): Flow<TransactionRecipient> fun getRecipients(transactionId: FirstClassByteArray): Flow<TransactionRecipient>

View File

@ -35,6 +35,19 @@ internal interface OutboundTransactionManager {
account: Account account: Account
): EncodedTransaction ): EncodedTransaction
/**
* Creates a proposal for transferring funds from a ZIP-321 compliant payment URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI
*
* @return the proposal or an exception
*/
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
/** /**
* Creates a proposal for transferring funds to the given recipient. * Creates a proposal for transferring funds to the given recipient.
* *

View File

@ -43,6 +43,18 @@ internal class OutboundTransactionManagerImpl(
} }
} }
/**
* Creates a proposal for transferring funds from a ZIP-321 compliant payment URI
*
* @param account the account from which to transfer funds.
* @param uri a ZIP-321 compliant payment URI
*
* @return the proposal or an exception
*/
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal = encoder.proposeTransferFromUri(account, uri)
override suspend fun proposeTransfer( override suspend fun proposeTransfer(
account: Account, account: Account,
recipient: String, recipient: String,

View File

@ -40,6 +40,19 @@ internal interface TransactionEncoder {
memo: ByteArray? = byteArrayOf() memo: ByteArray? = byteArrayOf()
): EncodedTransaction ): EncodedTransaction
/**
* Creates a proposal for transferring from a valid ZIP-321 Payment URI string
*
* @param account the account from which to transfer funds.
* @param uri a valid ZIP-321 Payment URI string
*
* @return the proposal or an exception
*/
suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal
/** /**
* Creates a proposal for transferring funds to the given recipient. * Creates a proposal for transferring funds to the given recipient.
* *

View File

@ -68,6 +68,36 @@ internal class TransactionEncoderImpl(
?: throw TransactionEncoderException.TransactionNotFoundException(transactionId) ?: throw TransactionEncoderException.TransactionNotFoundException(transactionId)
} }
/**
* Creates a proposal for transferring from a valid ZIP-321 Payment URI string
*
* @param account the account from which to transfer funds.
* @param uri a valid ZIP-321 Payment URI string
*
* @return the proposal or an exception
*/
override suspend fun proposeTransferFromUri(
account: Account,
uri: String
): Proposal {
Twig.debug {
"creating proposal from URI: $uri"
}
@Suppress("TooGenericExceptionCaught")
return try {
backend.proposeTransferFromUri(
account,
uri
)
} catch (t: Throwable) {
Twig.debug(t) { "Caught exception while creating proposal from URI String." }
throw t
}.also { result ->
Twig.debug { "result of proposeTransferFromUri: $result" }
}
}
override suspend fun proposeTransfer( override suspend fun proposeTransfer(
account: Account, account: Account,
recipient: String, recipient: String,

View File

@ -77,7 +77,7 @@ dependencyResolutionManagement {
} }
} }
@Suppress("UnstableApiUsage", "MaxLineLength") @Suppress("MaxLineLength")
versionCatalogs { versionCatalogs {
create("libs") { create("libs") {
val androidGradlePluginVersion = extra["ANDROID_GRADLE_PLUGIN_VERSION"].toString() val androidGradlePluginVersion = extra["ANDROID_GRADLE_PLUGIN_VERSION"].toString()
@ -98,7 +98,6 @@ dependencyResolutionManagement {
val androidxNavigationComposeVersion = extra["ANDROIDX_NAVIGATION_COMPOSE_VERSION"].toString() val androidxNavigationComposeVersion = extra["ANDROIDX_NAVIGATION_COMPOSE_VERSION"].toString()
val androidxNavigationFragmentVersion = extra["ANDROIDX_NAVIGATION_FRAGMENT_VERSION"].toString() val androidxNavigationFragmentVersion = extra["ANDROIDX_NAVIGATION_FRAGMENT_VERSION"].toString()
val androidxProfileInstallerVersion = extra["ANDROIDX_PROFILE_INSTALLER_VERSION"].toString() val androidxProfileInstallerVersion = extra["ANDROIDX_PROFILE_INSTALLER_VERSION"].toString()
val androidxRoomVersion = extra["ANDROIDX_ROOM_VERSION"].toString()
val androidxSecurityCryptoVersion = extra["ANDROIDX_SECURITY_CRYPTO_VERSION"].toString() val androidxSecurityCryptoVersion = extra["ANDROIDX_SECURITY_CRYPTO_VERSION"].toString()
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()
@ -108,7 +107,6 @@ dependencyResolutionManagement {
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()
val coroutinesOkhttpVersion = extra["COROUTINES_OKHTTP"].toString()
val flankVersion = extra["FLANK_VERSION"].toString() val flankVersion = extra["FLANK_VERSION"].toString()
val googleMaterialVersion = extra["GOOGLE_MATERIAL_VERSION"].toString() val googleMaterialVersion = extra["GOOGLE_MATERIAL_VERSION"].toString()
val grpcJavaVersion = extra["GRPC_VERSION"].toString() val grpcJavaVersion = extra["GRPC_VERSION"].toString()
@ -121,7 +119,6 @@ dependencyResolutionManagement {
val kotlinxCoroutinesVersion = extra["KOTLINX_COROUTINES_VERSION"].toString() val kotlinxCoroutinesVersion = extra["KOTLINX_COROUTINES_VERSION"].toString()
val kotlinxDateTimeVersion = extra["KOTLINX_DATETIME_VERSION"].toString() val kotlinxDateTimeVersion = extra["KOTLINX_DATETIME_VERSION"].toString()
val kotlinxImmutableCollectionsVersion = extra["KOTLINX_IMMUTABLE_COLLECTIONS_VERSION"].toString() val kotlinxImmutableCollectionsVersion = extra["KOTLINX_IMMUTABLE_COLLECTIONS_VERSION"].toString()
val mockitoKotlinVersion = extra["MOCKITO_KOTLIN_VERSION"].toString()
val mockitoVersion = extra["MOCKITO_VERSION"].toString() val mockitoVersion = extra["MOCKITO_VERSION"].toString()
val protocVersion = extra["PROTOC_VERSION"].toString() val protocVersion = extra["PROTOC_VERSION"].toString()
val rustGradlePluginVersion = extra["RUST_GRADLE_PLUGIN_VERSION"].toString() val rustGradlePluginVersion = extra["RUST_GRADLE_PLUGIN_VERSION"].toString()
@ -159,8 +156,6 @@ dependencyResolutionManagement {
library("androidx-navigation-fragment", "androidx.navigation:navigation-fragment-ktx:$androidxNavigationFragmentVersion") library("androidx-navigation-fragment", "androidx.navigation:navigation-fragment-ktx:$androidxNavigationFragmentVersion")
library("androidx-navigation-ui", "androidx.navigation:navigation-ui-ktx:$androidxNavigationVersion") library("androidx-navigation-ui", "androidx.navigation:navigation-ui-ktx:$androidxNavigationVersion")
library("androidx-profileinstaller", "androidx.profileinstaller:profileinstaller:$androidxProfileInstallerVersion") library("androidx-profileinstaller", "androidx.profileinstaller:profileinstaller:$androidxProfileInstallerVersion")
library("androidx-room-compiler", "androidx.room:room-compiler:$androidxRoomVersion")
library("androidx-room-core", "androidx.room:room-ktx:$androidxRoomVersion")
library("androidx-sqlite", "androidx.sqlite:sqlite-ktx:${androidxDatabaseVersion}") library("androidx-sqlite", "androidx.sqlite:sqlite-ktx:${androidxDatabaseVersion}")
library("androidx-sqlite-framework", "androidx.sqlite:sqlite-framework:${androidxDatabaseVersion}") library("androidx-sqlite-framework", "androidx.sqlite:sqlite-framework:${androidxDatabaseVersion}")
library("androidx-viewmodel-compose", "androidx.lifecycle:lifecycle-viewmodel-compose:$androidxLifecycleVersion") library("androidx-viewmodel-compose", "androidx.lifecycle:lifecycle-viewmodel-compose:$androidxLifecycleVersion")
@ -206,7 +201,6 @@ dependencyResolutionManagement {
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")
library("coroutines-okhttp", "ru.gildor.coroutines:kotlin-coroutines-okhttp:$coroutinesOkhttpVersion")
library("grpc-testing", "io.grpc:grpc-testing:$grpcJavaVersion") library("grpc-testing", "io.grpc:grpc-testing:$grpcJavaVersion")
library("junit-api", "org.junit.jupiter:junit-jupiter-api:$junitVersion") library("junit-api", "org.junit.jupiter:junit-jupiter-api:$junitVersion")
library("junit-engine", "org.junit.jupiter:junit-jupiter-engine:$junitVersion") library("junit-engine", "org.junit.jupiter:junit-jupiter-engine:$junitVersion")
@ -215,7 +209,6 @@ dependencyResolutionManagement {
library("kotlinx-coroutines-test", "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesVersion") library("kotlinx-coroutines-test", "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesVersion")
library("mockito-android", "org.mockito:mockito-android:$mockitoVersion") library("mockito-android", "org.mockito:mockito-android:$mockitoVersion")
library("mockito-junit", "org.mockito:mockito-junit-jupiter:$mockitoVersion") library("mockito-junit", "org.mockito:mockito-junit-jupiter:$mockitoVersion")
library("mockito-kotlin", "com.nhaarman.mockitokotlin2:mockito-kotlin:$mockitoKotlinVersion")
// Bundles // Bundles
bundle( bundle(