Implement versioning and other cleanup.
- Correct typo and compiler warning in Rust. 'trait objects without an explicity dyn' are deprecated and this is a warning as of Rust 1.37 - update dependencies - update documentation docs
This commit is contained in:
parent
636cbb59c0
commit
1f18042d52
33
README.md
33
README.md
|
@ -49,6 +49,7 @@ This lightweight SDK connects Android to Zcash. It welds together Rust and Kotli
|
|||
- [Components](#components)
|
||||
- [Quickstart](#quickstart)
|
||||
- [Compiling Sources](#compiling-sources)
|
||||
- [Versioning](#versioning)
|
||||
|
||||
## Structure
|
||||
|
||||
|
@ -84,20 +85,20 @@ To accomplish this, these responsibilities of the SDK are divided into separate
|
|||
|
||||
#### Components
|
||||
|
||||
| Component | Summary | Input | Output |
|
||||
| :--------- | :------------ | :--- | :--- |
|
||||
| **Downloader** | Downloads compact blocks | Server host:port | Stream of compact blocks |
|
||||
| **Processor** | Processes compact blocks | Stream of compact blocks | Decoded wallet data |
|
||||
| **Repository** | Source of data derived from processing blocks | Decoded wallet data | UI Data |
|
||||
| **Active Transaction Manager** | Manages the lifecycle of pending transactions | Decoded wallet data | Transaction state |
|
||||
| **Wallet** | Wraps the Zcash rust libraries, insulating SDK users from changes in that layer | Configuration | Configuration |
|
||||
|
||||
| Component | Summary |
|
||||
| :--------- | :------ |
|
||||
| **LightWalletService** | Service used for requesting compact blocks |
|
||||
| **CompactBlockStore** | Stores compact blocks that have been downloaded from the `LightWalletService` |
|
||||
| **CompactBlockProcessor** | Validates and scans the compact blocks in the `CompactBlockStore` for transaction details |
|
||||
| **TransactionManager** | Creates, Submits and manages transactions for spending funds |
|
||||
| **Wallet** | Wraps the Zcash rust libraries, insulating SDK users from changes in that layer |
|
||||
|
||||
[Back to contents](#contents)
|
||||
## Quickstart
|
||||
|
||||
Add the SDK dependency
|
||||
```gradle
|
||||
implementation "cash.z.android.wallet:zcash-android-testnet:1.7.5-alpha@aar"
|
||||
implementation "cash.z.android.wallet:zcash-android-testnet:1.0.0-alpha01@aar"
|
||||
```
|
||||
Start the [Synchronizer](docs/-synchronizer/README.md)
|
||||
|
||||
|
@ -127,4 +128,18 @@ Compilation requires `Cargo` and has been tested on Ubuntu, MacOS and Windows. T
|
|||
```
|
||||
This creates a `testnet` build of the SDK that can be used to preview basic functionality for sending and receiving shielded transactions. If you do not have `Rust` and `Cargo` installed, the build script will let you know and provide further instructions for installation. Note that merely using the SDK does not require installing Rust or Cargo--that is only required for compilation.
|
||||
|
||||
|
||||
[Back to contents](#contents)
|
||||
## Versioning
|
||||
|
||||
This project follows [semantic versioning](https://semver.org/) with pre-release versions. An example of a valid version number is `1.0.4-alpha11` denoting the `11th` iteration of the `alpha` pre-release of version `1.0.4`. Stable releases, such as `1.0.4` will not contain any pre-release identifiers. Pre-releases include the following, in order of stability: `alpha`, `beta`, `rc`. Version codes offer a numeric representation of the build name that always increases. The first six significant digits represent the major, minor and patch number (two digits each) and the last 3 significant digits represent the pre-release identifier. The first digit of the identifier signals the build type. Lastly, each new build has a higher version code than all previous builds. The following table breaks this down:
|
||||
|
||||
#### Build Types
|
||||
| Type | Purpose | Stability | Audience | Identifier | Example Version |
|
||||
| :---- | :--------- | :---------- | :-------- | :------- | :--- |
|
||||
| **alpha** | **Sandbox.** For developers to verify behavior and try features. Things seen here might never go to production. Most bugs here can be ignored.| Unstable: Expect bugs | Internal developers | 0XX | 1.2.3-alpha04 (10203004) |
|
||||
| **beta** | **Hand-off.** For developers to present finished features. Bugs found here should be reported and immediately addressed, if they relate to recent changes. | Unstable: Report bugs | Internal stakeholders | 2XX | 1.2.3-beta04 (10203204) |
|
||||
| **release candidate** | **Hardening.** Final testing for an app release that we believe is ready to go live. The focus here is regression testing to ensure that new changes have not introduced instability in areas that were previously working. | Stable: Hunt for bugs | External testers | 4XX | 1.2.3-rc04 (10203404) |
|
||||
| **production** | **Dellivery.** Deliver new features to end users. Any bugs found here need to be prioritized. Some will require immediate attention but most can be worked into a future release. | Stable: Prioritize bugs | Public | 8XX | 1.2.3 (10203800) |
|
||||
|
||||
[Back to contents](#contents)
|
||||
|
|
25
build.gradle
25
build.gradle
|
@ -1,16 +1,16 @@
|
|||
buildscript {
|
||||
ext.buildConfig = [
|
||||
'compileSdkVersion': 28,
|
||||
'compileSdkVersion': 29,
|
||||
'minSdkVersion': 16,
|
||||
'targetSdkVersion': 28
|
||||
'targetSdkVersion': 29
|
||||
]
|
||||
ext.versions = [
|
||||
'architectureComponents': [
|
||||
'lifecycle': '2.2.0-alpha02',
|
||||
'room': '2.1.0'
|
||||
'lifecycle': '2.2.0-alpha04',
|
||||
'room': '2.1.0-rc01'
|
||||
],
|
||||
'grpc':'1.21.0',
|
||||
'kotlin': '1.3.41',
|
||||
'kotlin': '1.3.50',
|
||||
'coroutines': '1.3.0-M1',
|
||||
'junitJupiter': '5.5.0-M1'
|
||||
]
|
||||
|
@ -22,7 +22,7 @@ buildscript {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0-beta05'
|
||||
classpath 'com.android.tools.build:gradle:3.6.0-alpha11'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}"
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.18"
|
||||
|
@ -31,13 +31,14 @@ buildscript {
|
|||
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.8"
|
||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.6'
|
||||
classpath 'com.github.str4d:rust-android-gradle:68b4ecc053'
|
||||
classpath 'org.owasp:dependency-check-gradle:5.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
apply from: 'custom-tasks.gradle'
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'kotlin-allopen'
|
||||
apply plugin: 'org.jetbrains.dokka'
|
||||
|
@ -49,7 +50,7 @@ apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
|
|||
apply plugin: 'org.owasp.dependencycheck'
|
||||
|
||||
group = 'cash.z.android.wallet'
|
||||
version = '1.9.1'
|
||||
version = '1.0.0-alpha01'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
|
@ -64,8 +65,8 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion buildConfig.minSdkVersion
|
||||
targetSdkVersion buildConfig.targetSdkVersion
|
||||
versionCode = 1_09_01_00 // last digits are alpha(0X) beta(1X) rc(2X) release(3X). Ex: 1_08_04_20 is a RC build
|
||||
versionName = "$version-alpha"
|
||||
versionCode = 1_00_00_001 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
|
||||
versionName = "$version"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
multiDexEnabled true
|
||||
|
@ -184,7 +185,7 @@ cargo {
|
|||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
|
||||
// Architecture Components: Lifecycle
|
||||
implementation "androidx.lifecycle:lifecycle-runtime:${versions.architectureComponents.lifecycle}"
|
||||
|
@ -232,7 +233,7 @@ dependencies {
|
|||
androidTestImplementation 'org.mockito:mockito-android:2.25.1'
|
||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||
androidTestImplementation "androidx.test:core:1.2.0"
|
||||
androidTestImplementation "androidx.arch.core:core-testing:2.0.1"
|
||||
androidTestImplementation "androidx.arch.core:core-testing:2.1.0-rc01"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
}
|
||||
|
|
|
@ -2,32 +2,23 @@
|
|||
|
||||
# <init>
|
||||
|
||||
`SdkSynchronizer(downloader: `[`CompactBlockStream`](../-compact-block-stream/index.md)`, processor: `[`CompactBlockProcessor`](../-compact-block-processor/index.md)`, repository: `[`TransactionRepository`](../-transaction-repository/index.md)`, activeTransactionManager: `[`ActiveTransactionManager`](../-active-transaction-manager/index.md)`, wallet: `[`Wallet`](../../cash.z.wallet.sdk.secure/-wallet/index.md)`, batchSize: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 1000, staleTolerance: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 10, blockPollFrequency: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = CompactBlockStream.DEFAULT_POLL_INTERVAL)`
|
||||
`SdkSynchronizer(wallet: `[`Wallet`](../../cash.z.wallet.sdk.secure/-wallet/index.md)`, ledger: `[`TransactionRepository`](../-transaction-repository/index.md)`, sender: `[`TransactionSender`](../-transaction-sender/index.md)`, processor: `[`CompactBlockProcessor`](../../cash.z.wallet.sdk.block/-compact-block-processor/index.md)`, encoder: `[`TransactionEncoder`](../-transaction-encoder/index.md)`)`
|
||||
|
||||
The glue. Downloads compact blocks to the database and then scans them for transactions. In order to serve that
|
||||
purpose, this class glues together a variety of key components. Each component contributes to the team effort of
|
||||
providing a simple source of truth to interact with.
|
||||
|
||||
Another way of thinking about this class is the reference that demonstrates how all the pieces can be tied
|
||||
together.
|
||||
A synchronizer that attempts to remain operational, despite any number of errors that can occur. It acts as the glue
|
||||
that ties all the pieces of the SDK together. Each component of the SDK is designed for the potential of stand-alone
|
||||
usage but coordinating all the interactions is non-trivial. So the synchronizer facilitates this, acting as reference
|
||||
that demonstrates how all the pieces can be tied together. Its goal is to allow a developer to focus on their app
|
||||
rather than the nuances of how Zcash works.
|
||||
|
||||
### Parameters
|
||||
|
||||
`downloader` - the component that downloads compact blocks and exposes them as a stream
|
||||
`wallet` - the component that wraps the JNI layer that interacts with the rust backend and manages wallet config.
|
||||
|
||||
`repository` - the component that exposes streams of wallet transaction information.
|
||||
|
||||
`sender` - the component responsible for sending transactions to lightwalletd in order to spend funds.
|
||||
|
||||
`processor` - the component that saves the downloaded compact blocks to the cache and then scans those blocks for
|
||||
data related to this wallet.
|
||||
|
||||
`repository` - the component that exposes streams of wallet transaction information.
|
||||
|
||||
`activeTransactionManager` - the component that manages the lifecycle of active transactions. This includes sent
|
||||
transactions that have not been mined.
|
||||
|
||||
`wallet` - the component that wraps the JNI layer that interacts with librustzcash and manages wallet config.
|
||||
|
||||
`batchSize` - the number of compact blocks to download at a time.
|
||||
|
||||
`staleTolerance` - the number of blocks to allow before considering our data to be stale
|
||||
|
||||
`blockPollFrequency` - how often to poll for compact blocks. Once all missing blocks have been downloaded, this
|
||||
number represents the number of milliseconds the synchronizer will wait before checking for newly mined blocks.
|
||||
`encoder` - the component that creates a signed transaction, used for spending funds.
|
|
@ -0,0 +1,10 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [balances](./balances.md)
|
||||
|
||||
# balances
|
||||
|
||||
`fun balances(): ReceiveChannel<`[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)`>`
|
||||
|
||||
Overrides [Synchronizer.balances](../-synchronizer/balances.md)
|
||||
|
||||
A stream of balance values, separately reflecting both the available and total balance.
|
||||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
# cancelSend
|
||||
|
||||
`fun cancelSend(transaction: `[`ActiveSendTransaction`](../-active-send-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
`fun cancelSend(transaction: `[`SentTransaction`](../../cash.z.wallet.sdk.entity/-sent-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
Overrides [Synchronizer.cancelSend](../-synchronizer/cancel-send.md)
|
||||
|
||||
Attempts to cancel a previously sent transaction. Transactions can only be cancelled during the calculation phase
|
||||
before they've been submitted to the server. This method will return false when it is too late to cancel. This
|
||||
logic is delegated to the activeTransactionManager, which knows the state of the given transaction.
|
||||
Attempts to cancel a previously sent transaction. Typically, cancellation is only an option if the transaction
|
||||
has not yet been submitted to the server.
|
||||
|
||||
### Parameters
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [clearedTransactions](./cleared-transactions.md)
|
||||
|
||||
# clearedTransactions
|
||||
|
||||
`fun clearedTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>>`
|
||||
|
||||
Overrides [Synchronizer.clearedTransactions](../-synchronizer/cleared-transactions.md)
|
||||
|
||||
A stream of all the transactions that are on the blockchain. Implementations should consider only returning a
|
||||
subset like the most recent 100 transactions, perhaps through paging the underlying database.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [coroutineScope](./coroutine-scope.md)
|
||||
|
||||
# coroutineScope
|
||||
|
||||
`lateinit var coroutineScope: CoroutineScope`
|
||||
|
||||
The lifespan of this Synchronizer. This scope is initialized once the Synchronizer starts because it will be a
|
||||
child of the parentScope that gets passed into the [start](start.md) function. Everything launched by this Synchronizer
|
||||
will be cancelled once the Synchronizer or its parentScope stops. This is a lateinit rather than nullable
|
||||
property so that it fails early rather than silently, whenever the scope is used before the Synchronizer has been
|
||||
started.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# getAddress
|
||||
|
||||
`fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
`suspend fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
Overrides [Synchronizer.getAddress](../-synchronizer/get-address.md)
|
||||
|
||||
|
@ -10,4 +10,4 @@ Gets the address for the given account.
|
|||
|
||||
### Parameters
|
||||
|
||||
`accountId` - the optional accountId whose address of interest. By default, the first account is used.
|
||||
`accountId` - the optional accountId whose address is of interest. By default, the first account is used.
|
|
@ -0,0 +1,61 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](./index.md)
|
||||
|
||||
# SdkSynchronizer
|
||||
|
||||
`@ExperimentalCoroutinesApi class SdkSynchronizer : `[`Synchronizer`](../-synchronizer/index.md)
|
||||
|
||||
A synchronizer that attempts to remain operational, despite any number of errors that can occur. It acts as the glue
|
||||
that ties all the pieces of the SDK together. Each component of the SDK is designed for the potential of stand-alone
|
||||
usage but coordinating all the interactions is non-trivial. So the synchronizer facilitates this, acting as reference
|
||||
that demonstrates how all the pieces can be tied together. Its goal is to allow a developer to focus on their app
|
||||
rather than the nuances of how Zcash works.
|
||||
|
||||
### Parameters
|
||||
|
||||
`wallet` - the component that wraps the JNI layer that interacts with the rust backend and manages wallet config.
|
||||
|
||||
`repository` - the component that exposes streams of wallet transaction information.
|
||||
|
||||
`sender` - the component responsible for sending transactions to lightwalletd in order to spend funds.
|
||||
|
||||
`processor` - the component that saves the downloaded compact blocks to the cache and then scans those blocks for
|
||||
data related to this wallet.
|
||||
|
||||
`encoder` - the component that creates a signed transaction, used for spending funds.
|
||||
|
||||
### Constructors
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [<init>](-init-.md) | `SdkSynchronizer(wallet: `[`Wallet`](../../cash.z.wallet.sdk.secure/-wallet/index.md)`, ledger: `[`TransactionRepository`](../-transaction-repository/index.md)`, sender: `[`TransactionSender`](../-transaction-sender/index.md)`, processor: `[`CompactBlockProcessor`](../../cash.z.wallet.sdk.block/-compact-block-processor/index.md)`, encoder: `[`TransactionEncoder`](../-transaction-encoder/index.md)`)`<br>A synchronizer that attempts to remain operational, despite any number of errors that can occur. It acts as the glue that ties all the pieces of the SDK together. Each component of the SDK is designed for the potential of stand-alone usage but coordinating all the interactions is non-trivial. So the synchronizer facilitates this, acting as reference that demonstrates how all the pieces can be tied together. Its goal is to allow a developer to focus on their app rather than the nuances of how Zcash works. |
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [coroutineScope](coroutine-scope.md) | `lateinit var coroutineScope: CoroutineScope`<br>The lifespan of this Synchronizer. This scope is initialized once the Synchronizer starts because it will be a child of the parentScope that gets passed into the [start](start.md) function. Everything launched by this Synchronizer will be cancelled once the Synchronizer or its parentScope stops. This is a lateinit rather than nullable property so that it fails early rather than silently, whenever the scope is used before the Synchronizer has been started. |
|
||||
| [isConnected](is-connected.md) | `val isConnected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A property that is true while a connection to the lightwalletd server exists. |
|
||||
| [isScanning](is-scanning.md) | `val isScanning: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A property that is true while actively scanning the cache of compact blocks for transactions. |
|
||||
| [isSyncing](is-syncing.md) | `val isSyncing: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A property that is true while actively downloading blocks from lightwalletd. |
|
||||
| [onCriticalErrorHandler](on-critical-error-handler.md) | `var onCriticalErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>A callback to invoke whenever an uncaught error is encountered. By definition, the return value of the function is ignored because this error is unrecoverable. The only reason the function has a return value is so that all error handlers work with the same signature which allows one function to handle all errors in simple apps. This callback is not called on the main thread so any UI work would need to switch context to the main thread. |
|
||||
| [onProcessorErrorHandler](on-processor-error-handler.md) | `var onProcessorErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>A callback to invoke whenver a processor error is encountered. Returning true signals that the error was handled and a retry attempt should be made, if possible. This callback is not called on the main thread so any UI work would need to switch context to the main thread. |
|
||||
| [onSubmissionErrorHandler](on-submission-error-handler.md) | `var onSubmissionErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>A callback to invoke whenever a server error is encountered while submitting a transaction to lightwalletd. Returning true signals that the error was handled and a retry attempt should be made, if possible. This callback is not called on the main thread so any UI work would need to switch context to the main thread. |
|
||||
|
||||
### Functions
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [balances](balances.md) | `fun balances(): ReceiveChannel<`[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)`>`<br>A stream of balance values, separately reflecting both the available and total balance. |
|
||||
| [cancelSend](cancel-send.md) | `fun cancelSend(transaction: `[`SentTransaction`](../../cash.z.wallet.sdk.entity/-sent-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>Attempts to cancel a previously sent transaction. Typically, cancellation is only an option if the transaction has not yet been submitted to the server. |
|
||||
| [clearedTransactions](cleared-transactions.md) | `fun clearedTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>>`<br>A stream of all the transactions that are on the blockchain. Implementations should consider only returning a subset like the most recent 100 transactions, perhaps through paging the underlying database. |
|
||||
| [getAddress](get-address.md) | `suspend fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>Gets the address for the given account. |
|
||||
| [lastBalance](last-balance.md) | `fun lastBalance(): `[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)<br>Holds the most recent value that was transmitted through the [balances](../-synchronizer/balances.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be), then this value is simply [balanceChannel.value](#) |
|
||||
| [lastCleared](last-cleared.md) | `fun lastCleared(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>`<br>Holds the most recent value that was transmitted through the [clearedTransactions](../-synchronizer/cleared-transactions.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be), then this value is simply [clearedChannel.value](#) |
|
||||
| [lastPending](last-pending.md) | `fun lastPending(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>`<br>Holds the most recent value that was transmitted through the [pendingTransactions](../-synchronizer/pending-transactions.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be),then this value is simply [pendingChannel.value](#) |
|
||||
| [onTransactionsChanged](on-transactions-changed.md) | `fun onTransactionsChanged(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) |
|
||||
| [pendingTransactions](pending-transactions.md) | `fun pendingTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>>`<br>A stream of all the outbound pending transaction that have been sent but are awaiting confirmations. |
|
||||
| [progress](progress.md) | `fun progress(): ReceiveChannel<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>`<br>A stream of progress values, typically corresponding to this Synchronizer downloading blocks. Typically, any non- zero value below 100 indicates that progress indicators can be shown and a value of 100 signals that progress is complete and any progress indicators can be hidden. |
|
||||
| [refreshBalance](refresh-balance.md) | `suspend fun refreshBalance(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) |
|
||||
| [sendToAddress](send-to-address.md) | `suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)<br>Sends zatoshi. |
|
||||
| [start](start.md) | `fun start(parentScope: CoroutineScope): `[`Synchronizer`](../-synchronizer/index.md)<br>Starts this synchronizer within the given scope. For simplicity, attempting to start an instance that has already been started will throw a [SynchronizerException.FalseStart](../../cash.z.wallet.sdk.exception/-synchronizer-exception/-false-start.md) exception. This reduces the complexity of managing resources that must be recycled. Instead, each synchronizer is designed to have a long lifespan and should be started from an activity, application or session. |
|
||||
| [stop](stop.md) | `fun stop(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)<br>Stop this synchronizer and all of its child jobs. Once a synchronizer has been stopped it should not be restarted and attempting to do so will result in an error. Also, this function will throw an exception if the synchronizer was never previously started. |
|
|
@ -0,0 +1,10 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [isConnected](./is-connected.md)
|
||||
|
||||
# isConnected
|
||||
|
||||
`val isConnected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
Overrides [Synchronizer.isConnected](../-synchronizer/is-connected.md)
|
||||
|
||||
A property that is true while a connection to the lightwalletd server exists.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [isScanning](./is-scanning.md)
|
||||
|
||||
# isScanning
|
||||
|
||||
`val isScanning: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
Overrides [Synchronizer.isScanning](../-synchronizer/is-scanning.md)
|
||||
|
||||
A property that is true while actively scanning the cache of compact blocks for transactions.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [isSyncing](./is-syncing.md)
|
||||
|
||||
# isSyncing
|
||||
|
||||
`val isSyncing: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
Overrides [Synchronizer.isSyncing](../-synchronizer/is-syncing.md)
|
||||
|
||||
A property that is true while actively downloading blocks from lightwalletd.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [lastBalance](./last-balance.md)
|
||||
|
||||
# lastBalance
|
||||
|
||||
`fun lastBalance(): `[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)
|
||||
|
||||
Overrides [Synchronizer.lastBalance](../-synchronizer/last-balance.md)
|
||||
|
||||
Holds the most recent value that was transmitted through the [balances](../-synchronizer/balances.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be), then this value is simply [balanceChannel.value](#)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [lastCleared](./last-cleared.md)
|
||||
|
||||
# lastCleared
|
||||
|
||||
`fun lastCleared(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>`
|
||||
|
||||
Overrides [Synchronizer.lastCleared](../-synchronizer/last-cleared.md)
|
||||
|
||||
Holds the most recent value that was transmitted through the [clearedTransactions](../-synchronizer/cleared-transactions.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be), then this value is simply [clearedChannel.value](#)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [lastPending](./last-pending.md)
|
||||
|
||||
# lastPending
|
||||
|
||||
`fun lastPending(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>`
|
||||
|
||||
Overrides [Synchronizer.lastPending](../-synchronizer/last-pending.md)
|
||||
|
||||
Holds the most recent value that was transmitted through the [pendingTransactions](../-synchronizer/pending-transactions.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be),then this value is simply [pendingChannel.value](#)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [onCriticalErrorHandler](./on-critical-error-handler.md)
|
||||
|
||||
# onCriticalErrorHandler
|
||||
|
||||
`var onCriticalErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
Overrides [Synchronizer.onCriticalErrorHandler](../-synchronizer/on-critical-error-handler.md)
|
||||
|
||||
A callback to invoke whenever an uncaught error is encountered. By definition, the return value of the function
|
||||
is ignored because this error is unrecoverable. The only reason the function has a return value is so that all
|
||||
error handlers work with the same signature which allows one function to handle all errors in simple apps. This
|
||||
callback is not called on the main thread so any UI work would need to switch context to the main thread.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [onProcessorErrorHandler](./on-processor-error-handler.md)
|
||||
|
||||
# onProcessorErrorHandler
|
||||
|
||||
`var onProcessorErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
Overrides [Synchronizer.onProcessorErrorHandler](../-synchronizer/on-processor-error-handler.md)
|
||||
|
||||
A callback to invoke whenver a processor error is encountered. Returning true signals that the error was handled
|
||||
and a retry attempt should be made, if possible. This callback is not called on the main thread so any UI work
|
||||
would need to switch context to the main thread.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [onSubmissionErrorHandler](./on-submission-error-handler.md)
|
||||
|
||||
# onSubmissionErrorHandler
|
||||
|
||||
`var onSubmissionErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
Overrides [Synchronizer.onSubmissionErrorHandler](../-synchronizer/on-submission-error-handler.md)
|
||||
|
||||
A callback to invoke whenever a server error is encountered while submitting a transaction to lightwalletd.
|
||||
Returning true signals that the error was handled and a retry attempt should be made, if possible. This callback
|
||||
is not called on the main thread so any UI work would need to switch context to the main thread.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [onTransactionsChanged](./on-transactions-changed.md)
|
||||
|
||||
# onTransactionsChanged
|
||||
|
||||
`fun onTransactionsChanged(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
|
@ -0,0 +1,10 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [pendingTransactions](./pending-transactions.md)
|
||||
|
||||
# pendingTransactions
|
||||
|
||||
`fun pendingTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>>`
|
||||
|
||||
Overrides [Synchronizer.pendingTransactions](../-synchronizer/pending-transactions.md)
|
||||
|
||||
A stream of all the outbound pending transaction that have been sent but are awaiting confirmations.
|
||||
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
Overrides [Synchronizer.progress](../-synchronizer/progress.md)
|
||||
|
||||
A stream of progress values, corresponding to this Synchronizer downloading blocks, delegated to the
|
||||
[downloader](#). Any non-zero value below 100 indicates that progress indicators can be shown and a value of 100
|
||||
signals that progress is complete and any progress indicators can be hidden. At that point, the synchronizer
|
||||
switches from catching up on missed blocks to periodically monitoring for newly mined blocks.
|
||||
A stream of progress values, typically corresponding to this Synchronizer downloading blocks. Typically, any non-
|
||||
zero value below 100 indicates that progress indicators can be shown and a value of 100 signals that progress is
|
||||
complete and any progress indicators can be hidden.
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [SdkSynchronizer](index.md) / [refreshBalance](./refresh-balance.md)
|
||||
|
||||
# refreshBalance
|
||||
|
||||
`suspend fun refreshBalance(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# sendToAddress
|
||||
|
||||
`suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
||||
`suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)
|
||||
|
||||
Overrides [Synchronizer.sendToAddress](../-synchronizer/send-to-address.md)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
Overrides [Synchronizer.stop](../-synchronizer/stop.md)
|
||||
|
||||
Stops this synchronizer by stopping the downloader, repository, and activeTransactionManager, then cancelling the
|
||||
parent job. Note that we do not cancel the parent scope that was passed into [start](start.md) because the synchronizer
|
||||
does not own that scope, it just uses it for launching children.
|
||||
Stop this synchronizer and all of its child jobs. Once a synchronizer has been stopped it should not be restarted
|
||||
and attempting to do so will result in an error. Also, this function will throw an exception if the synchronizer
|
||||
was never previously started.
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [balances](./balances.md)
|
||||
|
||||
# balances
|
||||
|
||||
`abstract fun balances(): ReceiveChannel<`[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)`>`
|
||||
|
||||
A stream of balance values, separately reflecting both the available and total balance.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# cancelSend
|
||||
|
||||
`abstract fun cancelSend(transaction: `[`ActiveSendTransaction`](../-active-send-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
`abstract fun cancelSend(transaction: `[`SentTransaction`](../../cash.z.wallet.sdk.entity/-sent-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
Attempts to cancel a previously sent transaction. Typically, cancellation is only an option if the transaction
|
||||
has not yet been submitted to the server.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [clearedTransactions](./cleared-transactions.md)
|
||||
|
||||
# clearedTransactions
|
||||
|
||||
`abstract fun clearedTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>>`
|
||||
|
||||
A stream of all the transactions that are on the blockchain. Implementations should consider only returning a
|
||||
subset like the most recent 100 transactions, perhaps through paging the underlying database.
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
# getAddress
|
||||
|
||||
`abstract fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
`abstract suspend fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
Gets the address for the given account.
|
||||
|
||||
### Parameters
|
||||
|
||||
`accountId` - the optional accountId whose address of interest. By default, the first account is used.
|
||||
`accountId` - the optional accountId whose address is of interest. By default, the first account is used.
|
|
@ -0,0 +1,44 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](./index.md)
|
||||
|
||||
# Synchronizer
|
||||
|
||||
`interface Synchronizer`
|
||||
|
||||
Primary interface for interacting with the SDK. Defines the contract that specific implementations like
|
||||
[MockSynchronizer](../-mock-synchronizer/index.md) and [SdkSynchronizer](../-sdk-synchronizer/index.md) fulfill. Given the language-level support for coroutines, we favor their
|
||||
use in the SDK and incorporate that choice into this contract.
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [isConnected](is-connected.md) | `abstract val isConnected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A flag indicating whether this Synchronizer is connected to its lightwalletd server. When false, a UI element may want to turn red. |
|
||||
| [isScanning](is-scanning.md) | `abstract val isScanning: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A flag indicating whether this Synchronizer is actively decrypting compact blocks, searching for transactions. When true, a UI element may want to turn yellow. |
|
||||
| [isSyncing](is-syncing.md) | `abstract val isSyncing: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>A flag indicating whether this Synchronizer is actively downloading compact blocks. When true, a UI element may want to turn yellow. |
|
||||
| [onCriticalErrorHandler](on-critical-error-handler.md) | `abstract var onCriticalErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>Gets or sets a global error handler. This is a useful hook for handling unexpected critical errors. |
|
||||
| [onProcessorErrorHandler](on-processor-error-handler.md) | `abstract var onProcessorErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>An error handler for exceptions during processing. For instance, a block might be missing or a reorg may get mishandled or the database may get corrupted. |
|
||||
| [onSubmissionErrorHandler](on-submission-error-handler.md) | `abstract var onSubmissionErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`<br>An error handler for exceptions while submitting transactions to lightwalletd. For instance, a transaction may get rejected because it would be a double-spend or the user might lose their cellphone signal. |
|
||||
|
||||
### Functions
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [balances](balances.md) | `abstract fun balances(): ReceiveChannel<`[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)`>`<br>A stream of balance values, separately reflecting both the available and total balance. |
|
||||
| [cancelSend](cancel-send.md) | `abstract fun cancelSend(transaction: `[`SentTransaction`](../../cash.z.wallet.sdk.entity/-sent-transaction/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)<br>Attempts to cancel a previously sent transaction. Typically, cancellation is only an option if the transaction has not yet been submitted to the server. |
|
||||
| [clearedTransactions](cleared-transactions.md) | `abstract fun clearedTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>>`<br>A stream of all the transactions that are on the blockchain. Implementations should consider only returning a subset like the most recent 100 transactions, perhaps through paging the underlying database. |
|
||||
| [getAddress](get-address.md) | `abstract suspend fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>Gets the address for the given account. |
|
||||
| [lastBalance](last-balance.md) | `abstract fun lastBalance(): `[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)<br>Holds the most recent value that was transmitted through the [balances](balances.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be), then this value is simply [balanceChannel.value](#) |
|
||||
| [lastCleared](last-cleared.md) | `abstract fun lastCleared(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>`<br>Holds the most recent value that was transmitted through the [clearedTransactions](cleared-transactions.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be), then this value is simply [clearedChannel.value](#) |
|
||||
| [lastPending](last-pending.md) | `abstract fun lastPending(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>`<br>Holds the most recent value that was transmitted through the [pendingTransactions](pending-transactions.md) channel. Typically, if the underlying channel is a BroadcastChannel (and it should be),then this value is simply [pendingChannel.value](#) |
|
||||
| [pendingTransactions](pending-transactions.md) | `abstract fun pendingTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>>`<br>A stream of all the outbound pending transaction that have been sent but are awaiting confirmations. |
|
||||
| [progress](progress.md) | `abstract fun progress(): ReceiveChannel<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>`<br>A stream of progress values, typically corresponding to this Synchronizer downloading blocks. Typically, any non- zero value below 100 indicates that progress indicators can be shown and a value of 100 signals that progress is complete and any progress indicators can be hidden. |
|
||||
| [sendToAddress](send-to-address.md) | `abstract suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "", fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)<br>Sends zatoshi. |
|
||||
| [start](start.md) | `abstract fun start(parentScope: CoroutineScope): `[`Synchronizer`](./index.md)<br>Starts this synchronizer within the given scope. |
|
||||
| [stop](stop.md) | `abstract fun stop(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)<br>Stop this synchronizer. Implementations should ensure that calling this method cancels all jobs that were created by this instance. |
|
||||
|
||||
### Inheritors
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [MockSynchronizer](../-mock-synchronizer/index.md) | `abstract class MockSynchronizer : `[`Synchronizer`](./index.md)`, CoroutineScope`<br>Utility for building UIs. It does the best it can to mock the SDKSynchronizer so that it can be dropped into any project and drive the UI. It generates active transactions in response to funds being sent and generates random received transactions, periodically. |
|
||||
| [SdkSynchronizer](../-sdk-synchronizer/index.md) | `class SdkSynchronizer : `[`Synchronizer`](./index.md)<br>A synchronizer that attempts to remain operational, despite any number of errors that can occur. It acts as the glue that ties all the pieces of the SDK together. Each component of the SDK is designed for the potential of stand-alone usage but coordinating all the interactions is non-trivial. So the synchronizer facilitates this, acting as reference that demonstrates how all the pieces can be tied together. Its goal is to allow a developer to focus on their app rather than the nuances of how Zcash works. |
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [isConnected](./is-connected.md)
|
||||
|
||||
# isConnected
|
||||
|
||||
`abstract val isConnected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
A flag indicating whether this Synchronizer is connected to its lightwalletd server. When false, a UI element
|
||||
may want to turn red.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [isScanning](./is-scanning.md)
|
||||
|
||||
# isScanning
|
||||
|
||||
`abstract val isScanning: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
A flag indicating whether this Synchronizer is actively decrypting compact blocks, searching for transactions.
|
||||
When true, a UI element may want to turn yellow.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [isSyncing](./is-syncing.md)
|
||||
|
||||
# isSyncing
|
||||
|
||||
`abstract val isSyncing: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
|
||||
|
||||
A flag indicating whether this Synchronizer is actively downloading compact blocks. When true, a UI element
|
||||
may want to turn yellow.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [lastBalance](./last-balance.md)
|
||||
|
||||
# lastBalance
|
||||
|
||||
`abstract fun lastBalance(): `[`Wallet.WalletBalance`](../../cash.z.wallet.sdk.secure/-wallet/-wallet-balance/index.md)
|
||||
|
||||
Holds the most recent value that was transmitted through the [balances](balances.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be), then this value is simply [balanceChannel.value](#)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [lastCleared](./last-cleared.md)
|
||||
|
||||
# lastCleared
|
||||
|
||||
`abstract fun lastCleared(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`ClearedTransaction`](../../cash.z.wallet.sdk.entity/-cleared-transaction/index.md)`>`
|
||||
|
||||
Holds the most recent value that was transmitted through the [clearedTransactions](cleared-transactions.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be), then this value is simply [clearedChannel.value](#)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [lastPending](./last-pending.md)
|
||||
|
||||
# lastPending
|
||||
|
||||
`abstract fun lastPending(): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>`
|
||||
|
||||
Holds the most recent value that was transmitted through the [pendingTransactions](pending-transactions.md) channel. Typically, if the
|
||||
underlying channel is a BroadcastChannel (and it should be),then this value is simply [pendingChannel.value](#)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [onCriticalErrorHandler](./on-critical-error-handler.md)
|
||||
|
||||
# onCriticalErrorHandler
|
||||
|
||||
`abstract var onCriticalErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
Gets or sets a global error handler. This is a useful hook for handling unexpected critical errors.
|
||||
|
||||
**Return**
|
||||
true when the error has been handled and the Synchronizer should attempt to continue. False when the
|
||||
error is unrecoverable and the Synchronizer should [stop](stop.md).
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [onProcessorErrorHandler](./on-processor-error-handler.md)
|
||||
|
||||
# onProcessorErrorHandler
|
||||
|
||||
`abstract var onProcessorErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
An error handler for exceptions during processing. For instance, a block might be missing or a reorg may get
|
||||
mishandled or the database may get corrupted.
|
||||
|
||||
**Return**
|
||||
true when the error has been handled and the processor should attempt to continue. False when the
|
||||
error is unrecoverable and the processor should [stop](stop.md).
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [onSubmissionErrorHandler](./on-submission-error-handler.md)
|
||||
|
||||
# onSubmissionErrorHandler
|
||||
|
||||
`abstract var onSubmissionErrorHandler: ((`[`Throwable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)`?) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`)?`
|
||||
|
||||
An error handler for exceptions while submitting transactions to lightwalletd. For instance, a transaction may
|
||||
get rejected because it would be a double-spend or the user might lose their cellphone signal.
|
||||
|
||||
**Return**
|
||||
true when the error has been handled and the sender should attempt to resend. False when the
|
||||
error is unrecoverable and the sender should [stop](stop.md).
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.data](../index.md) / [Synchronizer](index.md) / [pendingTransactions](./pending-transactions.md)
|
||||
|
||||
# pendingTransactions
|
||||
|
||||
`abstract fun pendingTransactions(): ReceiveChannel<`[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)`>>`
|
||||
|
||||
A stream of all the outbound pending transaction that have been sent but are awaiting confirmations.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# sendToAddress
|
||||
|
||||
`abstract suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "", fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
||||
`abstract suspend fun sendToAddress(zatoshi: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "", fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 0): `[`PendingTransaction`](../../cash.z.wallet.sdk.entity/-pending-transaction/index.md)
|
||||
|
||||
Sends zatoshi.
|
||||
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
|
||||
`abstract fun stop(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
||||
|
||||
Stop this synchronizer.
|
||||
Stop this synchronizer. Implementations should ensure that calling this method cancels all jobs that were created
|
||||
by this instance.
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [BIRTHDAY_DIRECTORY](./-b-i-r-t-h-d-a-y_-d-i-r-e-c-t-o-r-y.md)
|
||||
|
||||
# BIRTHDAY_DIRECTORY
|
||||
|
||||
`const val BIRTHDAY_DIRECTORY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
Directory within the assets folder where birthday data (i.e. sapling trees for a given height) can be found.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [CLOUD_PARAM_DIR_URL](./-c-l-o-u-d_-p-a-r-a-m_-d-i-r_-u-r-l.md)
|
||||
|
||||
# CLOUD_PARAM_DIR_URL
|
||||
|
||||
`const val CLOUD_PARAM_DIR_URL: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
The Url that is used by default in zcashd.
|
||||
We'll want to make this externally configurable, rather than baking it into the SDK but this will do for now,
|
||||
since we're using a cloudfront URL that already redirects.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [<init>](./-init-.md)
|
||||
|
||||
# <init>
|
||||
|
||||
`Wallet(context: Context, converter: `[`JniConverter`](../../cash.z.wallet.sdk.jni/-jni-converter/index.md)`, dataDbPath: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, paramDestinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, accountIds: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`> = arrayOf(0), seedProvider: `[`ReadOnlyProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-only-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`ByteArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-byte-array/index.html)`>, spendingKeyProvider: `[`ReadWriteProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-write-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>)``Wallet(birthday: `[`Wallet.WalletBirthday`](-wallet-birthday/index.md)`, converter: `[`JniConverter`](../../cash.z.wallet.sdk.jni/-jni-converter/index.md)`, dataDbPath: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, paramDestinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, accountIds: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`> = arrayOf(0), seedProvider: `[`ReadOnlyProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-only-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`ByteArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-byte-array/index.html)`>, spendingKeyProvider: `[`ReadWriteProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-write-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>)`
|
||||
|
||||
Wrapper for the converter. This class basically represents all the Rust-wallet capabilities and the supporting data
|
||||
required to exercise those abilities.
|
||||
|
||||
### Parameters
|
||||
|
||||
`birthday` - the birthday of this wallet. See [WalletBirthday](-wallet-birthday/index.md) for more info.
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [OUTPUT_PARAM_FILE_NAME](./-o-u-t-p-u-t_-p-a-r-a-m_-f-i-l-e_-n-a-m-e.md)
|
||||
|
||||
# OUTPUT_PARAM_FILE_NAME
|
||||
|
||||
`const val OUTPUT_PARAM_FILE_NAME: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
File name for the sapling output params
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [SPEND_PARAM_FILE_NAME](./-s-p-e-n-d_-p-a-r-a-m_-f-i-l-e_-n-a-m-e.md)
|
||||
|
||||
# SPEND_PARAM_FILE_NAME
|
||||
|
||||
`const val SPEND_PARAM_FILE_NAME: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
File name for the sappling spend params
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBalance](index.md) / [<init>](./-init-.md)
|
||||
|
||||
# <init>
|
||||
|
||||
`WalletBalance(total: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1, available: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1)`
|
||||
|
||||
Data structure to hold the total and available balance of the wallet. This is what is received on the balance
|
||||
channel.
|
||||
|
||||
### Parameters
|
||||
|
||||
`total` - the total balance, ignoring funds that cannot be used.
|
||||
|
||||
`available` - the amount of funds that are available for use. Typical reasons that funds may be unavailable
|
||||
include fairly new transactions that do not have enough confirmations or notes that are tied up because we are
|
||||
awaiting change from a transaction. When a note has been spent, its change cannot be used until there are enough
|
||||
confirmations.
|
|
@ -1,30 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBalance](./index.md)
|
||||
|
||||
# WalletBalance
|
||||
|
||||
`data class WalletBalance`
|
||||
|
||||
Data structure to hold the total and available balance of the wallet. This is what is received on the balance
|
||||
channel.
|
||||
|
||||
### Parameters
|
||||
|
||||
`total` - the total balance, ignoring funds that cannot be used.
|
||||
|
||||
`available` - the amount of funds that are available for use. Typical reasons that funds may be unavailable
|
||||
include fairly new transactions that do not have enough confirmations or notes that are tied up because we are
|
||||
awaiting change from a transaction. When a note has been spent, its change cannot be used until there are enough
|
||||
confirmations.
|
||||
|
||||
### Constructors
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [<init>](-init-.md) | `WalletBalance(total: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1, available: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1)`<br>Data structure to hold the total and available balance of the wallet. This is what is received on the balance channel. |
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [available](available.md) | `val available: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)<br>the amount of funds that are available for use. Typical reasons that funds may be unavailable include fairly new transactions that do not have enough confirmations or notes that are tied up because we are awaiting change from a transaction. When a note has been spent, its change cannot be used until there are enough confirmations. |
|
||||
| [total](total.md) | `val total: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)<br>the total balance, ignoring funds that cannot be used. |
|
|
@ -1,11 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBalance](index.md) / [available](./available.md)
|
||||
|
||||
# available
|
||||
|
||||
`val available: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
|
||||
|
||||
the amount of funds that are available for use. Typical reasons that funds may be unavailable
|
||||
include fairly new transactions that do not have enough confirmations or notes that are tied up because we are
|
||||
awaiting change from a transaction. When a note has been spent, its change cannot be used until there are enough
|
||||
confirmations.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBalance](index.md) / [total](./total.md)
|
||||
|
||||
# total
|
||||
|
||||
`val total: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
|
||||
|
||||
the total balance, ignoring funds that cannot be used.
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBirthday](index.md) / [<init>](./-init-.md)
|
||||
|
||||
# <init>
|
||||
|
||||
`WalletBirthday(height: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = -1, time: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1, tree: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "")`
|
||||
|
||||
Represents the wallet's birthday which can be thought of as a checkpoint at the earliest moment in history where
|
||||
transactions related to this wallet could exist. Ideally, this would correspond to the latest block height at the
|
||||
time the wallet key was created. Worst case, the height of Sapling activation could be used (280000).
|
||||
|
||||
Knowing a wallet's birthday can significantly reduce the amount of data that it needs to download because none of
|
||||
the data before that height needs to be scanned for transactions. However, we do need the Sapling tree data in
|
||||
order to construct valid transactions from that point forward. This birthday contains that tree data, allowing us
|
||||
to avoid downloading all the compact blocks required in order to generate it.
|
||||
|
||||
Currently, the data for this is generated by running `cargo run --release --features=updater` with the SDK and
|
||||
saving the resulting JSON to the `src/main/assets/zcash` folder. That script simply builds a Sapling tree from
|
||||
the start of Sapling activation up to the latest block height. In the future, this data could be exposed as a
|
||||
service on the lightwalletd server because every zcashd node already maintains the sapling tree for each block.
|
||||
For now, we just include the latest checkpoint in each SDK release.
|
||||
|
||||
New wallets can ignore any blocks created before their birthday.
|
||||
|
||||
### Parameters
|
||||
|
||||
`height` - the height at the time the wallet was born
|
||||
|
||||
`time` - the time the wallet was born, in seconds
|
||||
|
||||
`tree` - the sapling tree corresponding to the given height. This takes around 15 minutes of processing to
|
||||
generate from scratch because all blocks since activation need to be considered. So when it is calculated in
|
||||
advance it can save the user a lot of time.
|
|
@ -1,46 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBirthday](./index.md)
|
||||
|
||||
# WalletBirthday
|
||||
|
||||
`data class WalletBirthday`
|
||||
|
||||
Represents the wallet's birthday which can be thought of as a checkpoint at the earliest moment in history where
|
||||
transactions related to this wallet could exist. Ideally, this would correspond to the latest block height at the
|
||||
time the wallet key was created. Worst case, the height of Sapling activation could be used (280000).
|
||||
|
||||
Knowing a wallet's birthday can significantly reduce the amount of data that it needs to download because none of
|
||||
the data before that height needs to be scanned for transactions. However, we do need the Sapling tree data in
|
||||
order to construct valid transactions from that point forward. This birthday contains that tree data, allowing us
|
||||
to avoid downloading all the compact blocks required in order to generate it.
|
||||
|
||||
Currently, the data for this is generated by running `cargo run --release --features=updater` with the SDK and
|
||||
saving the resulting JSON to the `src/main/assets/zcash` folder. That script simply builds a Sapling tree from
|
||||
the start of Sapling activation up to the latest block height. In the future, this data could be exposed as a
|
||||
service on the lightwalletd server because every zcashd node already maintains the sapling tree for each block.
|
||||
For now, we just include the latest checkpoint in each SDK release.
|
||||
|
||||
New wallets can ignore any blocks created before their birthday.
|
||||
|
||||
### Parameters
|
||||
|
||||
`height` - the height at the time the wallet was born
|
||||
|
||||
`time` - the time the wallet was born, in seconds
|
||||
|
||||
`tree` - the sapling tree corresponding to the given height. This takes around 15 minutes of processing to
|
||||
generate from scratch because all blocks since activation need to be considered. So when it is calculated in
|
||||
advance it can save the user a lot of time.
|
||||
|
||||
### Constructors
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [<init>](-init-.md) | `WalletBirthday(height: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = -1, time: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = -1, tree: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "")`<br>Represents the wallet's birthday which can be thought of as a checkpoint at the earliest moment in history where transactions related to this wallet could exist. Ideally, this would correspond to the latest block height at the time the wallet key was created. Worst case, the height of Sapling activation could be used (280000). |
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [height](height.md) | `val height: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)<br>the height at the time the wallet was born |
|
||||
| [time](time.md) | `val time: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)<br>the time the wallet was born, in seconds |
|
||||
| [tree](tree.md) | `val tree: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>the sapling tree corresponding to the given height. This takes around 15 minutes of processing to generate from scratch because all blocks since activation need to be considered. So when it is calculated in advance it can save the user a lot of time. |
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBirthday](index.md) / [height](./height.md)
|
||||
|
||||
# height
|
||||
|
||||
`val height: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
|
||||
|
||||
the height at the time the wallet was born
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBirthday](index.md) / [time](./time.md)
|
||||
|
||||
# time
|
||||
|
||||
`val time: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
|
||||
|
||||
the time the wallet was born, in seconds
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../../index.md) / [cash.z.wallet.sdk.secure](../../index.md) / [Wallet](../index.md) / [WalletBirthday](index.md) / [tree](./tree.md)
|
||||
|
||||
# tree
|
||||
|
||||
`val tree: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
the sapling tree corresponding to the given height. This takes around 15 minutes of processing to
|
||||
generate from scratch because all blocks since activation need to be considered. So when it is calculated in
|
||||
advance it can save the user a lot of time.
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](./index.md)
|
||||
|
||||
# Wallet
|
||||
|
||||
`class Wallet`
|
||||
|
||||
Wrapper for the converter. This class basically represents all the Rust-wallet capabilities and the supporting data
|
||||
required to exercise those abilities.
|
||||
|
||||
### Parameters
|
||||
|
||||
`birthday` - the birthday of this wallet. See [WalletBirthday](-wallet-birthday/index.md) for more info.
|
||||
|
||||
### Types
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [WalletBalance](-wallet-balance/index.md) | `data class WalletBalance`<br>Data structure to hold the total and available balance of the wallet. This is what is received on the balance channel. |
|
||||
| [WalletBirthday](-wallet-birthday/index.md) | `data class WalletBirthday`<br>Represents the wallet's birthday which can be thought of as a checkpoint at the earliest moment in history where transactions related to this wallet could exist. Ideally, this would correspond to the latest block height at the time the wallet key was created. Worst case, the height of Sapling activation could be used (280000). |
|
||||
|
||||
### Constructors
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [<init>](-init-.md) | `Wallet(context: Context, converter: `[`JniConverter`](../../cash.z.wallet.sdk.jni/-jni-converter/index.md)`, dataDbPath: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, paramDestinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, accountIds: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`> = arrayOf(0), seedProvider: `[`ReadOnlyProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-only-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`ByteArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-byte-array/index.html)`>, spendingKeyProvider: `[`ReadWriteProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-write-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>)``Wallet(birthday: `[`Wallet.WalletBirthday`](-wallet-birthday/index.md)`, converter: `[`JniConverter`](../../cash.z.wallet.sdk.jni/-jni-converter/index.md)`, dataDbPath: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, paramDestinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, accountIds: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`> = arrayOf(0), seedProvider: `[`ReadOnlyProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-only-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`ByteArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-byte-array/index.html)`>, spendingKeyProvider: `[`ReadWriteProperty`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-write-property/index.html)`<`[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`?, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>)`<br>Wrapper for the converter. This class basically represents all the Rust-wallet capabilities and the supporting data required to exercise those abilities. |
|
||||
|
||||
### Functions
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [balance](balance.md) | `fun balance(): ReceiveChannel<`[`Wallet.WalletBalance`](-wallet-balance/index.md)`>`<br>Stream of balances. |
|
||||
| [createRawSendTransaction](create-raw-send-transaction.md) | `suspend fun createRawSendTransaction(value: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "", fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)<br>Does the proofs and processing required to create a raw transaction and inserts the result in the database. On average, this call takes over 10 seconds. |
|
||||
| [fetchParams](fetch-params.md) | `suspend fun fetchParams(destinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)<br>Download and store the params into the given directory. |
|
||||
| [getAddress](get-address.md) | `fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>Gets the address for this wallet, defaulting to the first account. |
|
||||
| [initialize](initialize.md) | `fun initialize(firstRunStartHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = SAPLING_ACTIVATION_HEIGHT): `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)<br>Initializes the wallet by creating the DataDb and pre-populating it with data corresponding to the birthday for this wallet. |
|
||||
| [sendBalanceInfo](send-balance-info.md) | `suspend fun sendBalanceInfo(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)<br>Calculates the latest balance info and emits it into the balance channel. Defaults to the first account. |
|
||||
|
||||
### Companion Object Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [BIRTHDAY_DIRECTORY](-b-i-r-t-h-d-a-y_-d-i-r-e-c-t-o-r-y.md) | `const val BIRTHDAY_DIRECTORY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>Directory within the assets folder where birthday data (i.e. sapling trees for a given height) can be found. |
|
||||
| [CLOUD_PARAM_DIR_URL](-c-l-o-u-d_-p-a-r-a-m_-d-i-r_-u-r-l.md) | `const val CLOUD_PARAM_DIR_URL: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>The Url that is used by default in zcashd. We'll want to make this externally configurable, rather than baking it into the SDK but this will do for now, since we're using a cloudfront URL that already redirects. |
|
||||
| [OUTPUT_PARAM_FILE_NAME](-o-u-t-p-u-t_-p-a-r-a-m_-f-i-l-e_-n-a-m-e.md) | `const val OUTPUT_PARAM_FILE_NAME: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>File name for the sapling output params |
|
||||
| [SPEND_PARAM_FILE_NAME](-s-p-e-n-d_-p-a-r-a-m_-f-i-l-e_-n-a-m-e.md) | `const val SPEND_PARAM_FILE_NAME: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)<br>File name for the sappling spend params |
|
||||
|
||||
### Companion Object Functions
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [loadBirthdayFromAssets](load-birthday-from-assets.md) | `fun loadBirthdayFromAssets(context: Context, birthdayHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`? = null): `[`Wallet.WalletBirthday`](-wallet-birthday/index.md)<br>Load the given birthday file from the assets of the given context. When no height is specified, we default to the file with the greatest name. |
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [balance](./balance.md)
|
||||
|
||||
# balance
|
||||
|
||||
`fun balance(): ReceiveChannel<`[`Wallet.WalletBalance`](-wallet-balance/index.md)`>`
|
||||
|
||||
Stream of balances.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [createRawSendTransaction](./create-raw-send-transaction.md)
|
||||
|
||||
# createRawSendTransaction
|
||||
|
||||
`suspend fun createRawSendTransaction(value: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, toAddress: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, memo: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = "", fromAccountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
|
||||
|
||||
Does the proofs and processing required to create a raw transaction and inserts the result in the database. On
|
||||
average, this call takes over 10 seconds.
|
||||
|
||||
### Parameters
|
||||
|
||||
`value` - the zatoshi value to send
|
||||
|
||||
`toAddress` - the destination address
|
||||
|
||||
`memo` - the memo, which is not augmented in any way
|
||||
|
||||
**Return**
|
||||
the row id in the transactions table that contains the raw transaction or -1 if it failed
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [fetchParams](./fetch-params.md)
|
||||
|
||||
# fetchParams
|
||||
|
||||
`suspend fun fetchParams(destinationDir: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
||||
|
||||
Download and store the params into the given directory.
|
||||
|
||||
### Parameters
|
||||
|
||||
`destinationDir` - the directory where the params will be stored. It's assumed that we have write access to
|
||||
this directory. Typically, this should be the app's cache directory because it is not harmful if these files are
|
||||
cleared by the user since they are downloaded on-demand.
|
|
@ -1,8 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [getAddress](./get-address.md)
|
||||
|
||||
# getAddress
|
||||
|
||||
`fun getAddress(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
|
||||
|
||||
Gets the address for this wallet, defaulting to the first account.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [initialize](./initialize.md)
|
||||
|
||||
# initialize
|
||||
|
||||
`fun initialize(firstRunStartHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = SAPLING_ACTIVATION_HEIGHT): `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
|
||||
|
||||
Initializes the wallet by creating the DataDb and pre-populating it with data corresponding to the birthday for
|
||||
this wallet.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [loadBirthdayFromAssets](./load-birthday-from-assets.md)
|
||||
|
||||
# loadBirthdayFromAssets
|
||||
|
||||
`fun loadBirthdayFromAssets(context: Context, birthdayHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`? = null): `[`Wallet.WalletBirthday`](-wallet-birthday/index.md)
|
||||
|
||||
Load the given birthday file from the assets of the given context. When no height is specified, we default to
|
||||
the file with the greatest name.
|
||||
|
||||
### Parameters
|
||||
|
||||
`context` - the context from which to load assets.
|
||||
|
||||
`birthdayHeight` - the height file to look for among the file names.
|
||||
|
||||
**Return**
|
||||
a WalletBirthday that reflects the contents of the file or an exception when parsing fails.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
[zcash-android-wallet-sdk](../../index.md) / [cash.z.wallet.sdk.secure](../index.md) / [Wallet](index.md) / [sendBalanceInfo](./send-balance-info.md)
|
||||
|
||||
# sendBalanceInfo
|
||||
|
||||
`suspend fun sendBalanceInfo(accountId: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = accountIds[0]): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
|
||||
|
||||
Calculates the latest balance info and emits it into the balance channel. Defaults to the first account.
|
||||
|
||||
### Parameters
|
||||
|
||||
`accountId` - the account to check for balance info.
|
|
@ -1,6 +1,6 @@
|
|||
#Fri Jun 07 02:04:27 EDT 2019
|
||||
#Wed Sep 11 23:39:49 EDT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
|
||||
|
|
|
@ -3,11 +3,11 @@ apply plugin: 'kotlin-android'
|
|||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "cash.z.wallet.sdk.sample.address"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -23,11 +23,11 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(path: ':sdk')
|
||||
implementation project(path: ':sdk')
|
||||
// api project(path: ':sdk', configuration: 'default')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.core:core-ktx:1.0.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}"
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
buildscript {
|
||||
ext.versions = [
|
||||
'kotlin': '1.3.31',
|
||||
'coroutines': '1.3.0-M1'
|
||||
'kotlin': '1.3.50',
|
||||
'coroutines': '1.3.0-M1'
|
||||
]
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0-beta04'
|
||||
classpath 'com.android.tools.build:gradle:3.6.0-alpha11'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
|
||||
|
|
|
@ -5,11 +5,11 @@ apply plugin: 'kotlin-android'
|
|||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "cash.z.wallet.sdk.sample.memo"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -27,13 +27,13 @@ android {
|
|||
dependencies {
|
||||
implementation project(path: ':sdk', configuration: 'default')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.core:core-ktx:1.0.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
compile project(path: ':sdk')
|
||||
implementation project(path: ':sdk')
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import cash.z.wallet.sdk.block.CompactBlockDownloader
|
|||
import cash.z.wallet.sdk.block.CompactBlockProcessor
|
||||
import cash.z.wallet.sdk.block.ProcessorConfig
|
||||
import cash.z.wallet.sdk.data.*
|
||||
import cash.z.wallet.sdk.ext.SampleSeedProvider
|
||||
import cash.z.wallet.sdk.ext.SimpleProvider
|
||||
import cash.z.wallet.sdk.jni.RustBackend
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import cash.z.wallet.sdk.service.LightWalletGrpcService
|
||||
|
@ -18,12 +20,21 @@ object Injection {
|
|||
private val rustBackend = RustBackend()
|
||||
|
||||
fun provideSynchronizer(appContext: Context): Synchronizer {
|
||||
val config = ProcessorConfig(cacheDbName.toDbPath(appContext), dataDbName.toDbPath(appContext), downloadBatchSize = 1_000) // settings
|
||||
val service = LightWalletGrpcService(appContext, host, port) // connects to lightwalletd
|
||||
val blockStore = CompactBlockDbStore(appContext, cacheDbName) // enables compact block storage in cache
|
||||
val downloader = CompactBlockDownloader(service, blockStore) // downloads blocks an puts them in storage
|
||||
val repository = PollingTransactionRepository(appContext, dataDbName, rustBackend) // provides access to txs
|
||||
val processor = CompactBlockProcessor(config, downloader, repository, rustBackend) // decrypts compact blocks
|
||||
|
||||
// ledger
|
||||
val ledger = PollingTransactionRepository(appContext, dataDbName)
|
||||
|
||||
// sender
|
||||
val manager = PersistentTransactionManager(appContext)
|
||||
val service = LightWalletGrpcService(appContext, host, port)
|
||||
val sender = PersistentTransactionSender(manager, service, ledger)
|
||||
|
||||
// processor
|
||||
val config = ProcessorConfig(cacheDbName.toDbPath(appContext), dataDbName.toDbPath(appContext))
|
||||
val blockStore = CompactBlockDbStore(appContext, cacheDbName)
|
||||
val downloader = CompactBlockDownloader(service, blockStore)
|
||||
val processor = CompactBlockProcessor(config, downloader, ledger, rustBackend)
|
||||
|
||||
// wrapper for rustbackend
|
||||
val wallet = Wallet(
|
||||
context = appContext,
|
||||
|
@ -33,10 +44,18 @@ object Injection {
|
|||
seedProvider = SampleSeedProvider("testreferencecarol"),
|
||||
spendingKeyProvider = SimpleProvider("dummyValue")
|
||||
)
|
||||
val activeTransactionManager = ActiveTransactionManager(repository, service, wallet) // monitors active txs
|
||||
|
||||
// Encoder
|
||||
val encoder = WalletTransactionEncoder(wallet, ledger)
|
||||
|
||||
// ties everything together
|
||||
return SdkSynchronizer(processor, repository, activeTransactionManager, wallet)
|
||||
return SdkSynchronizer(
|
||||
wallet,
|
||||
ledger,
|
||||
sender,
|
||||
processor,
|
||||
encoder
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.toDbPath(context: Context): String {
|
||||
|
|
|
@ -11,6 +11,7 @@ import cash.z.wallet.sdk.secure.Wallet
|
|||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.properties.Delegates
|
||||
|
@ -20,13 +21,11 @@ import kotlin.reflect.KProperty
|
|||
class MainActivity : ScopedActivity() {
|
||||
|
||||
private lateinit var synchronizer: Synchronizer
|
||||
private var progressJob: Job? = null
|
||||
private var balanceJob: Job? = null
|
||||
private var activeTransaction: TransactionInfo = TransactionInfo()
|
||||
private var loaded: Boolean by observable(false) {_, old: Boolean, new: Boolean ->
|
||||
if (!old && new) {
|
||||
launch {
|
||||
onBalance(synchronizer.getBalance())
|
||||
onBalance(synchronizer.lastBalance())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,23 +39,14 @@ class MainActivity : ScopedActivity() {
|
|||
|
||||
synchronizer = Injection.provideSynchronizer(this.applicationContext)
|
||||
synchronizer.start(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressJob = launchProgressMonitor(synchronizer.progress())
|
||||
balanceJob = launchBalanceMonitor(synchronizer.balances())
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressJob?.cancel().also { progressJob = null }
|
||||
balanceJob?.cancel().also { balanceJob = null }
|
||||
launchProgressMonitor(synchronizer.progress())
|
||||
launchBalanceMonitor(synchronizer.balances())
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
cancel()
|
||||
synchronizer.stop()
|
||||
}
|
||||
|
||||
|
@ -66,11 +56,11 @@ class MainActivity : ScopedActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.launchTransactionMonitor(channel: ReceiveChannel<Map<ActiveTransaction, TransactionState>>) = launch {
|
||||
for (i in channel) {
|
||||
onUpdate(i)
|
||||
}
|
||||
}
|
||||
// private fun CoroutineScope.launchTransactionMonitor(channel: ReceiveChannel<Map<ActiveTransaction, TransactionState>>) = launch {
|
||||
// for (i in channel) {
|
||||
// onUpdate(i)
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun CoroutineScope.launchBalanceMonitor(channel: ReceiveChannel<Wallet.WalletBalance>) = launch {
|
||||
for (i in channel) {
|
||||
|
@ -98,23 +88,23 @@ class MainActivity : ScopedActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun onUpdate(transactions: Map<ActiveTransaction, TransactionState>) {
|
||||
if (transactions.isNotEmpty()) {
|
||||
// primary is the last one that was inserted
|
||||
val primaryEntry =
|
||||
transactions.entries.toTypedArray()[transactions.size - 1]
|
||||
updatePrimaryTransaction(primaryEntry.key, primaryEntry.value)
|
||||
}
|
||||
}
|
||||
// private fun onUpdate(transactions: Map<ActiveTransaction, TransactionState>) {
|
||||
// if (transactions.isNotEmpty()) {
|
||||
// // primary is the last one that was inserted
|
||||
// val primaryEntry =
|
||||
// transactions.entries.toTypedArray()[transactions.size - 1]
|
||||
// updatePrimaryTransaction(primaryEntry.key, primaryEntry.value)
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun updatePrimaryTransaction(transaction: ActiveTransaction,
|
||||
transactionState: TransactionState) {
|
||||
val status = transactionState.toString()
|
||||
text_status.text = "Memo Sent!\nAwaiting confirmation...\nstatus: $status"
|
||||
}
|
||||
// private fun updatePrimaryTransaction(transaction: ActiveTransaction,
|
||||
// transactionState: TransactionState) {
|
||||
// val status = transactionState.toString()
|
||||
// text_status.text = "Memo Sent!\nAwaiting confirmation...\nstatus: $status"
|
||||
// }
|
||||
|
||||
fun onSendMemo(v: View) {
|
||||
launchTransactionMonitor(synchronizer.activeTransactions())
|
||||
// launchTransactionMonitor(synchronizer.activeTransactions())
|
||||
|
||||
activeTransaction = TransactionInfo(memo = input_memo.text.toString())
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
buildscript {
|
||||
ext.versions = [
|
||||
'kotlin': '1.3.31',
|
||||
'kotlin': '1.3.50',
|
||||
'coroutines': '1.3.0-M1'
|
||||
]
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0-beta04'
|
||||
classpath 'com.android.tools.build:gradle:3.6.0-alpha11'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +17,6 @@ allprojects {
|
|||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Thu Jun 20 02:36:23 EDT 2019
|
||||
#Wed Sep 11 21:21:29 EDT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.room.Room
|
|||
import androidx.room.RoomDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import cash.z.wallet.sdk.entity.CompactBlock
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import cash.z.wallet.sdk.jni.RustBackend
|
||||
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||
import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc
|
||||
|
@ -42,8 +41,8 @@ class GlueIntegrationTest {
|
|||
private fun addData() {
|
||||
val result = blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(373070.toBlockHeight())
|
||||
.setEnd(373085.toBlockHeight())
|
||||
.setStart(BlockID.newBuilder().setHeight(373070L).build())
|
||||
.setEnd(BlockID.newBuilder().setHeight(373085L).build())
|
||||
.build()
|
||||
)
|
||||
while (result.hasNext()) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.room.Room
|
|||
import androidx.room.RoomDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import cash.z.wallet.sdk.entity.CompactBlock
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import cash.z.wallet.sdk.jni.RustBackend
|
||||
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||
import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc
|
||||
|
@ -44,8 +43,8 @@ class GlueSetupIntegrationTest {
|
|||
private fun addData() {
|
||||
val result = blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(373070.toBlockHeight())
|
||||
.setEnd(373085.toBlockHeight())
|
||||
.setStart(BlockID.newBuilder().setHeight(373070L).build())
|
||||
.setEnd(BlockID.newBuilder().setHeight(373085L).build())
|
||||
.build()
|
||||
)
|
||||
while (result.hasNext()) {
|
||||
|
|
|
@ -71,7 +71,7 @@ class IntegrationTest {
|
|||
)
|
||||
|
||||
// repository.start(this)
|
||||
// synchronizer = StableSynchronizer(wallet, repository, , processor)
|
||||
// synchronizer = SdkSynchronizer(wallet, repository, , processor)
|
||||
// processor,
|
||||
// repository,
|
||||
// ActiveTransactionManager(repository, lightwalletService, wallet),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package cash.z.wallet.sdk.jni
|
||||
|
||||
import android.text.format.DateUtils
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.BeforeClass
|
||||
|
@ -38,7 +37,7 @@ class RustBackendTest {
|
|||
|
||||
@Test
|
||||
fun testSend() {
|
||||
rustBackend.sendToAddress(
|
||||
rustBackend.createToAddress(
|
||||
"/data/user/0/cash.z.wallet.sdk.test/databases/data2.db",
|
||||
0,
|
||||
"dummykey",
|
||||
|
@ -52,12 +51,6 @@ class RustBackendTest {
|
|||
|
||||
companion object {
|
||||
val rustBackend: RustBackendWelding = RustBackend()
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
rustBackend.initLogs()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,10 +13,14 @@ import kotlinx.coroutines.Dispatchers.IO
|
|||
* Repository that does polling for simplicity. We will implement an alternative version that uses live data as well as
|
||||
* one that creates triggers and then reference them here. For now this is the most basic example of keeping track of
|
||||
* changes.
|
||||
*
|
||||
* @param limit the max number of transactions to return when polling for changes. After a wallet has been a round for a
|
||||
* long time, returning ALL transactions might be overkill. Instead, it may be more efficient to only return a limited
|
||||
* number of transactions, like the most recent transaction that has changed.
|
||||
*/
|
||||
open class PollingTransactionRepository(
|
||||
private val derivedDataDb: DerivedDataDb,
|
||||
private val pollFrequencyMillis: Long = 2000L,
|
||||
private val pollFrequencyMillis: Long = DEFAULT_TX_POLL_INTERVAL_MS,
|
||||
private val limit: Int = Int.MAX_VALUE
|
||||
) : TransactionRepository {
|
||||
|
||||
|
@ -26,7 +30,7 @@ open class PollingTransactionRepository(
|
|||
constructor(
|
||||
context: Context,
|
||||
dataDbName: String,
|
||||
pollFrequencyMillis: Long = 2000L
|
||||
pollFrequencyMillis: Long = DEFAULT_TX_POLL_INTERVAL_MS
|
||||
) : this(
|
||||
Room.databaseBuilder(context, DerivedDataDb::class.java, dataDbName)
|
||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||
|
@ -89,7 +93,7 @@ open class PollingTransactionRepository(
|
|||
twig("Notifying listener that changes have been detected in transactions!")
|
||||
listener.invoke()
|
||||
} else {
|
||||
twig("No changes detected in transactions.")
|
||||
//twig("No changes detected in transactions.")
|
||||
}
|
||||
delay(pollFrequencyMillis)
|
||||
}
|
||||
|
@ -101,6 +105,9 @@ open class PollingTransactionRepository(
|
|||
derivedDataDb.close()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_TX_POLL_INTERVAL_MS = 5_000L
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,305 +0,0 @@
|
|||
// This has been replaced by "StableSynchronizer" We keep it around for the docs
|
||||
|
||||
|
||||
//package cash.z.wallet.sdk.data
|
||||
//
|
||||
//import cash.z.wallet.sdk.block.CompactBlockProcessor
|
||||
//import cash.z.wallet.sdk.entity.ClearedTransaction
|
||||
//import cash.z.wallet.sdk.exception.SynchronizerException
|
||||
//import cash.z.wallet.sdk.exception.WalletException
|
||||
//import cash.z.wallet.sdk.secure.Wallet
|
||||
//import kotlinx.coroutines.*
|
||||
//import kotlinx.coroutines.Dispatchers.IO
|
||||
//import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
//import kotlinx.coroutines.channels.ReceiveChannel
|
||||
//import kotlinx.coroutines.channels.distinct
|
||||
//import kotlin.coroutines.CoroutineContext
|
||||
//
|
||||
///**
|
||||
// * The glue. Downloads compact blocks to the database and then scans them for transactions. In order to serve that
|
||||
// * purpose, this class glues together a variety of key components. Each component contributes to the team effort of
|
||||
// * providing a simple source of truth to interact with.
|
||||
// *
|
||||
// * Another way of thinking about this class is the reference that demonstrates how all the pieces can be tied
|
||||
// * together.
|
||||
// *
|
||||
// * @param processor the component that saves the downloaded compact blocks to the cache and then scans those blocks for
|
||||
// * data related to this wallet.
|
||||
// * @param repository the component that exposes streams of wallet transaction information.
|
||||
// * @param activeTransactionManager the component that manages the lifecycle of active transactions. This includes sent
|
||||
// * transactions that have not been mined.
|
||||
// * @param wallet the component that wraps the JNI layer that interacts with librustzcash and manages wallet config.
|
||||
// * @param batchSize the number of compact blocks to download at a time.
|
||||
// * @param staleTolerance the number of blocks to allow before considering our data to be stale
|
||||
// * @param blockPollFrequency how often to poll for compact blocks. Once all missing blocks have been downloaded, this
|
||||
// * number represents the number of milliseconds the synchronizer will wait before checking for newly mined blocks.
|
||||
// */
|
||||
//class SdkSynchronizer(
|
||||
// private val processor: CompactBlockProcessor,
|
||||
// private val repository: TransactionRepository,
|
||||
// private val activeTransactionManager: ActiveTransactionManager,
|
||||
// private val wallet: Wallet,
|
||||
// private val staleTolerance: Int = 10
|
||||
//) : Synchronizer {
|
||||
//
|
||||
// /**
|
||||
// * The primary job for this Synchronizer. It leverages structured concurrency to cancel all work when the
|
||||
// * `parentScope` provided to the [start] method ends.
|
||||
// */
|
||||
// private lateinit var blockJob: Job
|
||||
//
|
||||
// /**
|
||||
// * The state this Synchronizer was in when it started. This is helpful because the conditions that lead to FirstRun
|
||||
// * or isStale being detected can change quickly so retaining the initial state is useful for walkthroughs or other
|
||||
// * elements of an app that need to rely on this information later, rather than in realtime.
|
||||
// */
|
||||
// private lateinit var initialState: SyncState
|
||||
//
|
||||
// /**
|
||||
// * Returns true when `start` has been called on this synchronizer.
|
||||
// */
|
||||
// private val wasPreviouslyStarted
|
||||
// get() = ::blockJob.isInitialized
|
||||
//
|
||||
// /**
|
||||
// * Retains the error that caused this synchronizer to fail for future error handling or reporting.
|
||||
// */
|
||||
// private var failure: Throwable? = null
|
||||
//
|
||||
// /**
|
||||
// * The default exception handler for the block job. Calls [onException].
|
||||
// */
|
||||
// private val exceptionHandler: (c: CoroutineContext, t: Throwable) -> Unit = { _, t -> onException(t) }
|
||||
//
|
||||
// /**
|
||||
// * Sets a listener to be notified of uncaught Synchronizer errors. When null, errors will only be logged.
|
||||
// */
|
||||
// override var onSynchronizerErrorListener: ((Throwable?) -> Boolean)? = null
|
||||
// set(value) {
|
||||
// field = value
|
||||
// if (failure != null) value?.invoke(failure)
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Channel of transactions from the repository.
|
||||
// */
|
||||
// private val transactionChannel = ConflatedBroadcastChannel<List<ClearedTransaction>>()
|
||||
//
|
||||
// /**
|
||||
// * Channel of balance information.
|
||||
// */
|
||||
// private val balanceChannel = ConflatedBroadcastChannel<Wallet.WalletBalance>()
|
||||
//
|
||||
// //
|
||||
// // Public API
|
||||
// //
|
||||
//
|
||||
// /* Lifecycle */
|
||||
//
|
||||
// /**
|
||||
// * Starts this synchronizer within the given scope. For simplicity, attempting to start an instance that has already
|
||||
// * been started will throw a [SynchronizerException.FalseStart] exception. This reduces the complexity of managing
|
||||
// * resources that must be recycled. Instead, each synchronizer is designed to have a long lifespan and should be
|
||||
// * started from an activity, application or session.
|
||||
// *
|
||||
// * @param parentScope the scope to use for this synchronizer, typically something with a lifecycle such as an
|
||||
// * Activity for single-activity apps or a logged in user session. This scope is only used for launching this
|
||||
// * synchronzer's job as a child.
|
||||
// */
|
||||
// override fun start(parentScope: CoroutineScope): Synchronizer {
|
||||
// // prevent restarts so the behavior of this class is easier to reason about
|
||||
// if (wasPreviouslyStarted) throw SynchronizerException.FalseStart
|
||||
// twig("starting")
|
||||
// failure = null
|
||||
// blockJob = parentScope.launch(CoroutineExceptionHandler(exceptionHandler)) {
|
||||
// supervisorScope {
|
||||
// try {
|
||||
// wallet.initialize()
|
||||
// } catch (e: WalletException.AlreadyInitializedException) {
|
||||
// twig("Warning: wallet already initialized but this is safe to ignore " +
|
||||
// "because the SDK now automatically detects where to start downloading.")
|
||||
// }
|
||||
// onReady()
|
||||
// }
|
||||
// }
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Stops this synchronizer by stopping the downloader, repository, and activeTransactionManager, then cancelling the
|
||||
// * parent job. Note that we do not cancel the parent scope that was passed into [start] because the synchronizer
|
||||
// * does not own that scope, it just uses it for launching children.
|
||||
// */
|
||||
// override fun stop() {
|
||||
// twig("stopping")
|
||||
// (repository as? PollingTransactionRepository)?.stop().also { twig("repository stopped") }
|
||||
// activeTransactionManager.stop().also { twig("activeTransactionManager stopped") }
|
||||
// // TODO: investigate whether this is necessary and remove or improve, accordingly
|
||||
// Thread.sleep(5000L)
|
||||
// blockJob.cancel().also { twig("blockJob cancelled") }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /* Channels */
|
||||
//
|
||||
// /**
|
||||
// * A stream of all the wallet transactions, delegated to the [activeTransactionManager].
|
||||
// */
|
||||
// override fun activeTransactions() = activeTransactionManager.subscribe()
|
||||
//
|
||||
// /**
|
||||
// * A stream of all the wallet transactions, delegated to the [repository].
|
||||
// */
|
||||
// override fun allTransactions(): ReceiveChannel<List<ClearedTransaction>> {
|
||||
// return transactionChannel.openSubscription()
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * A stream of progress values, corresponding to this Synchronizer downloading blocks, delegated to the
|
||||
// * [downloader]. Any non-zero value below 100 indicates that progress indicators can be shown and a value of 100
|
||||
// * signals that progress is complete and any progress indicators can be hidden. At that point, the synchronizer
|
||||
// * switches from catching up on missed blocks to periodically monitoring for newly mined blocks.
|
||||
// */
|
||||
// override fun progress(): ReceiveChannel<Int> {
|
||||
// return processor.progress()
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * A stream of balance values, delegated to the [wallet].
|
||||
// */
|
||||
// override fun balances(): ReceiveChannel<Wallet.WalletBalance> {
|
||||
// return balanceChannel.openSubscription()
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /* Status */
|
||||
//
|
||||
// /**
|
||||
// * A flag to indicate that this Synchronizer is significantly out of sync with it's server. This is determined by
|
||||
// * the delta between the current block height reported by the server and the latest block we have stored in cache.
|
||||
// * Whenever this delta is greater than the [staleTolerance], this function returns true. This is intended for
|
||||
// * showing progress indicators when the user returns to the app after having not used it for a long period.
|
||||
// * Typically, this means the user may have to wait for downloading to occur and the current balance and transaction
|
||||
// * information cannot be trusted as 100% accurate.
|
||||
// *
|
||||
// * @return true when the local data is significantly out of sync with the remote server and the app data is stale.
|
||||
// */
|
||||
// override suspend fun isStale(): Boolean = withContext(IO) {
|
||||
// val latestBlockHeight = processor.downloader.getLatestBlockHeight()
|
||||
// val ourHeight = processor.downloader.getLastDownloadedHeight()
|
||||
// val tolerance = staleTolerance
|
||||
// val delta = latestBlockHeight - ourHeight
|
||||
// twig("checking whether out of sync. " +
|
||||
// "LatestHeight: $latestBlockHeight ourHeight: $ourHeight Delta: $delta tolerance: $tolerance")
|
||||
// delta > tolerance
|
||||
// }
|
||||
//
|
||||
// /* Operations */
|
||||
//
|
||||
// /**
|
||||
// * Gets the address for the given account.
|
||||
// *
|
||||
// * @param accountId the optional accountId whose address of interest. Typically, this value is zero.
|
||||
// */
|
||||
// override fun getAddress(accountId: Int): String = wallet.getAddress()
|
||||
//
|
||||
// override suspend fun getBalance(accountId: Int): Wallet.WalletBalance = wallet.getBalanceInfo(accountId)
|
||||
//
|
||||
// /**
|
||||
// * Sends zatoshi.
|
||||
// *
|
||||
// * @param zatoshi the amount of zatoshi to send.
|
||||
// * @param toAddress the recipient's address.
|
||||
// * @param memo the optional memo to include as part of the transaction.
|
||||
// * @param fromAccountId the optional account id to use. By default, the first account is used.
|
||||
// */
|
||||
// override suspend fun sendToAddress(zatoshi: Long, toAddress: String, memo: String, fromAccountId: Int) =
|
||||
// activeTransactionManager.sendToAddress(zatoshi, toAddress, memo, fromAccountId)
|
||||
//
|
||||
// /**
|
||||
// * Attempts to cancel a previously sent transaction. Transactions can only be cancelled during the calculation phase
|
||||
// * before they've been submitted to the server. This method will return false when it is too late to cancel. This
|
||||
// * logic is delegated to the activeTransactionManager, which knows the state of the given transaction.
|
||||
// *
|
||||
// * @param transaction the transaction to cancel.
|
||||
// * @return true when the cancellation request was successful. False when it is too late to cancel.
|
||||
// */
|
||||
// override fun cancelSend(transaction: ActiveSendTransaction): Boolean = activeTransactionManager.cancel(transaction)
|
||||
//
|
||||
//
|
||||
// //
|
||||
// // Private API
|
||||
// //
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Logic for starting the Synchronizer once it is ready for processing. All starts eventually end with this method.
|
||||
// */
|
||||
// private fun CoroutineScope.onReady() = launch {
|
||||
// twig("synchronization is ready to begin!")
|
||||
// launch { monitorTransactions(transactionChannel.openSubscription().distinct()) }
|
||||
//
|
||||
// activeTransactionManager.start()
|
||||
// repository.poll(transactionChannel)
|
||||
// processor.start()
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Monitors transactions and recalculates the balance any time transactions have changed.
|
||||
// */
|
||||
// private suspend fun monitorTransactions(transactionChannel: ReceiveChannel<List<ClearedTransaction>>) =
|
||||
// withContext(IO) {
|
||||
// twig("beginning to monitor transactions in order to update the balance")
|
||||
// launch {
|
||||
// for (i in transactionChannel) {
|
||||
// twig("triggering a balance update because transactions have changed")
|
||||
// balanceChannel.send(wallet.getBalanceInfo())
|
||||
// twig("done triggering balance check!")
|
||||
// }
|
||||
// }
|
||||
// twig("done monitoring transactions in order to update the balance")
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Wraps exceptions, logs them and then invokes the [onSynchronizerErrorListener], if it exists.
|
||||
// */
|
||||
// private fun onException(throwable: Throwable) {
|
||||
// twig("********")
|
||||
// twig("******** ERROR: $throwable")
|
||||
// if (throwable.cause != null) twig("******** caused by ${throwable.cause}")
|
||||
// if (throwable.cause?.cause != null) twig("******** caused by ${throwable.cause?.cause}")
|
||||
// twig("********")
|
||||
//
|
||||
// val hasRecovered = onSynchronizerErrorListener?.invoke(throwable)
|
||||
// if (hasRecovered != true) stop().also { failure = throwable }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Represents the initial state of the Synchronizer.
|
||||
// */
|
||||
// sealed class SyncState {
|
||||
// /**
|
||||
// * State for the first run of the Synchronizer, when the database has not been initialized.
|
||||
// */
|
||||
// object FirstRun : SyncState()
|
||||
//
|
||||
// /**
|
||||
// * State for when compact blocks have been downloaded but not scanned. This state is typically achieved when the
|
||||
// * app was previously started but killed before the first scan took place. In this case, we do not need to
|
||||
// * download compact blocks that we already have.
|
||||
// *
|
||||
// * @param startingBlockHeight the last block that has been downloaded into the cache. We do not need to download
|
||||
// * any blocks before this height because we already have them.
|
||||
// */
|
||||
// class CacheOnly(val startingBlockHeight: Int = Int.MAX_VALUE) : SyncState()
|
||||
//
|
||||
// /**
|
||||
// * The final state of the Synchronizer, when all initialization is complete and the starting block is known.
|
||||
// *
|
||||
// * @param startingBlockHeight the height that will be fed to the downloader. In most cases, it will represent
|
||||
// * either the wallet birthday or the last block that was processed in the previous session.
|
||||
// */
|
||||
// class ReadyToProcess(val startingBlockHeight: Int = Int.MAX_VALUE) : SyncState()
|
||||
// }
|
||||
//
|
||||
//}
|
|
@ -4,6 +4,7 @@ import cash.z.wallet.sdk.block.CompactBlockProcessor
|
|||
import cash.z.wallet.sdk.entity.ClearedTransaction
|
||||
import cash.z.wallet.sdk.entity.PendingTransaction
|
||||
import cash.z.wallet.sdk.entity.SentTransaction
|
||||
import cash.z.wallet.sdk.exception.SynchronizerException
|
||||
import cash.z.wallet.sdk.exception.WalletException
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -13,10 +14,21 @@ import kotlinx.coroutines.channels.ReceiveChannel
|
|||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* A synchronizer that attempts to remain operational, despite any number of errors that can occur.
|
||||
* A synchronizer that attempts to remain operational, despite any number of errors that can occur. It acts as the glue
|
||||
* that ties all the pieces of the SDK together. Each component of the SDK is designed for the potential of stand-alone
|
||||
* usage but coordinating all the interactions is non-trivial. So the synchronizer facilitates this, acting as reference
|
||||
* that demonstrates how all the pieces can be tied together. Its goal is to allow a developer to focus on their app
|
||||
* rather than the nuances of how Zcash works.
|
||||
*
|
||||
* @param wallet the component that wraps the JNI layer that interacts with the rust backend and manages wallet config.
|
||||
* @param repository the component that exposes streams of wallet transaction information.
|
||||
* @param sender the component responsible for sending transactions to lightwalletd in order to spend funds.
|
||||
* @param processor the component that saves the downloaded compact blocks to the cache and then scans those blocks for
|
||||
* data related to this wallet.
|
||||
* @param encoder the component that creates a signed transaction, used for spending funds.
|
||||
*/
|
||||
@ExperimentalCoroutinesApi
|
||||
class StableSynchronizer (
|
||||
class SdkSynchronizer (
|
||||
private val wallet: Wallet,
|
||||
private val ledger: TransactionRepository,
|
||||
private val sender: TransactionSender,
|
||||
|
@ -34,39 +46,86 @@ class StableSynchronizer (
|
|||
lateinit var coroutineScope: CoroutineScope
|
||||
|
||||
|
||||
//
|
||||
// Communication Primitives
|
||||
//
|
||||
|
||||
private val balanceChannel = ConflatedBroadcastChannel(Wallet.WalletBalance())
|
||||
private val progressChannel = ConflatedBroadcastChannel(0)
|
||||
private val pendingChannel = ConflatedBroadcastChannel<List<PendingTransaction>>(listOf())
|
||||
private val clearedChannel = ConflatedBroadcastChannel<List<ClearedTransaction>>(listOf())
|
||||
|
||||
|
||||
//
|
||||
// Status
|
||||
//
|
||||
|
||||
/**
|
||||
* A property that is true while a connection to the lightwalletd server exists.
|
||||
*/
|
||||
override val isConnected: Boolean get() = processor.isConnected
|
||||
|
||||
/**
|
||||
* A property that is true while actively downloading blocks from lightwalletd.
|
||||
*/
|
||||
override val isSyncing: Boolean get() = processor.isSyncing
|
||||
|
||||
/**
|
||||
* A property that is true while actively scanning the cache of compact blocks for transactions.
|
||||
*/
|
||||
override val isScanning: Boolean get() = processor.isScanning
|
||||
|
||||
|
||||
//
|
||||
// Communication Primitives
|
||||
//
|
||||
|
||||
/**
|
||||
* Channel of balance information.
|
||||
*/
|
||||
private val balanceChannel = ConflatedBroadcastChannel(Wallet.WalletBalance())
|
||||
|
||||
/**
|
||||
* Channel of data representing transactions that are pending.
|
||||
*/
|
||||
private val pendingChannel = ConflatedBroadcastChannel<List<PendingTransaction>>(listOf())
|
||||
|
||||
/**
|
||||
* Channel of data representing transactions that have been mined.
|
||||
*/
|
||||
private val clearedChannel = ConflatedBroadcastChannel<List<ClearedTransaction>>(listOf())
|
||||
|
||||
|
||||
//
|
||||
// Error Handling
|
||||
//
|
||||
|
||||
/*
|
||||
* These listeners will not be called on the main thread.
|
||||
* So they will need to switch to do anything with UI, like dialogs
|
||||
/**
|
||||
* A callback to invoke whenever an uncaught error is encountered. By definition, the return value of the function
|
||||
* is ignored because this error is unrecoverable. The only reason the function has a return value is so that all
|
||||
* error handlers work with the same signature which allows one function to handle all errors in simple apps. This
|
||||
* callback is not called on the main thread so any UI work would need to switch context to the main thread.
|
||||
*/
|
||||
override var onCriticalErrorHandler: ((Throwable?) -> Boolean)? = null
|
||||
|
||||
/**
|
||||
* A callback to invoke whenver a processor error is encountered. Returning true signals that the error was handled
|
||||
* and a retry attempt should be made, if possible. This callback is not called on the main thread so any UI work
|
||||
* would need to switch context to the main thread.
|
||||
*/
|
||||
override var onProcessorErrorHandler: ((Throwable?) -> Boolean)? = null
|
||||
|
||||
/**
|
||||
* A callback to invoke whenever a server error is encountered while submitting a transaction to lightwalletd.
|
||||
* Returning true signals that the error was handled and a retry attempt should be made, if possible. This callback
|
||||
* is not called on the main thread so any UI work would need to switch context to the main thread.
|
||||
*/
|
||||
override var onSubmissionErrorHandler: ((Throwable?) -> Boolean)? = null
|
||||
|
||||
|
||||
/**
|
||||
* Starts this synchronizer within the given scope. For simplicity, attempting to start an instance that has already
|
||||
* been started will throw a [SynchronizerException.FalseStart] exception. This reduces the complexity of managing
|
||||
* resources that must be recycled. Instead, each synchronizer is designed to have a long lifespan and should be
|
||||
* started from an activity, application or session.
|
||||
*
|
||||
* @param parentScope the scope to use for this synchronizer, typically something with a lifecycle such as an
|
||||
* Activity for single-activity apps or a logged in user session. This scope is only used for launching this
|
||||
* synchronzer's job as a child.
|
||||
*/
|
||||
override fun start(parentScope: CoroutineScope): Synchronizer {
|
||||
if (::coroutineScope.isInitialized) throw SynchronizerException.FalseStart
|
||||
|
||||
// base this scope on the parent so that when the parent's job cancels, everything here cancels as well
|
||||
// also use a supervisor job so that one failure doesn't bring down the whole synchronizer
|
||||
coroutineScope = CoroutineScope(SupervisorJob(parentScope.coroutineContext[Job]!!) + Dispatchers.Main)
|
||||
|
@ -84,12 +143,18 @@ class StableSynchronizer (
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the sender such that it can initiate requests within the scope of this synchronizer.
|
||||
*/
|
||||
private fun startSender(parentScope: CoroutineScope) {
|
||||
sender.onSubmissionError = ::onFailedSend
|
||||
sender.start(parentScope)
|
||||
}
|
||||
|
||||
private suspend fun initWallet() = withContext(Dispatchers.IO) {
|
||||
/**
|
||||
* Initialize the wallet, which involves populating data tables based on the latest state of the wallet.
|
||||
*/
|
||||
private suspend fun initWallet() = withContext(IO) {
|
||||
try {
|
||||
wallet.initialize()
|
||||
} catch (e: WalletException.AlreadyInitializedException) {
|
||||
|
@ -104,6 +169,8 @@ class StableSynchronizer (
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: this is a work in progress. We could take drastic measures to automatically recover from certain critical
|
||||
// errors and alert the user but this might be better to do at the app level, rather than SDK level.
|
||||
private fun recoverFrom(error: WalletException.FalseStart): Boolean {
|
||||
if (error.message?.contains("unable to open database file") == true
|
||||
|| error.message?.contains("table blocks has no column named") == true) {
|
||||
|
@ -113,6 +180,11 @@ class StableSynchronizer (
|
|||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop this synchronizer and all of its child jobs. Once a synchronizer has been stopped it should not be restarted
|
||||
* and attempting to do so will result in an error. Also, this function will throw an exception if the synchronizer
|
||||
* was never previously started.
|
||||
*/
|
||||
override fun stop() {
|
||||
coroutineScope.cancel()
|
||||
}
|
||||
|
@ -157,6 +229,7 @@ class StableSynchronizer (
|
|||
|
||||
fun onTransactionsChanged() {
|
||||
coroutineScope.launch {
|
||||
twig("triggering a balance update because transactions have changed")
|
||||
refreshBalance()
|
||||
clearedChannel.send(ledger.getClearedTransactions())
|
||||
}
|
||||
|
@ -165,7 +238,6 @@ class StableSynchronizer (
|
|||
|
||||
suspend fun refreshBalance() = withContext(IO) {
|
||||
if (!balanceChannel.isClosedForSend) {
|
||||
twig("triggering a balance update because transactions have changed")
|
||||
balanceChannel.send(wallet.getBalanceInfo())
|
||||
} else {
|
||||
twig("WARNING: noticed new transactions but the balance channel was closed for send so ignoring!")
|
||||
|
@ -212,9 +284,7 @@ class StableSynchronizer (
|
|||
return balanceChannel.openSubscription()
|
||||
}
|
||||
|
||||
override fun progress(): ReceiveChannel<Int> {
|
||||
return progressChannel.openSubscription()
|
||||
}
|
||||
override fun progress(): ReceiveChannel<Int> = processor.progress()
|
||||
|
||||
override fun pendingTransactions(): ReceiveChannel<List<PendingTransaction>> {
|
||||
return pendingChannel.openSubscription()
|
||||
|
|
|
@ -9,7 +9,7 @@ import kotlinx.coroutines.channels.ReceiveChannel
|
|||
|
||||
/**
|
||||
* Primary interface for interacting with the SDK. Defines the contract that specific implementations like
|
||||
* [MockSynchronizer] and [StableSynchronizer] fulfill. Given the language-level support for coroutines, we favor their
|
||||
* [MockSynchronizer] and [SdkSynchronizer] fulfill. Given the language-level support for coroutines, we favor their
|
||||
* use in the SDK and incorporate that choice into this contract.
|
||||
*/
|
||||
interface Synchronizer {
|
||||
|
|
|
@ -18,7 +18,7 @@ class WalletTransactionEncoder(
|
|||
* double-bangs for things).
|
||||
*/
|
||||
override suspend fun create(zatoshi: Long, toAddress: String, memo: String): EncodedTransaction = withContext(IO) {
|
||||
val transactionId = wallet.createRawSendTransaction(zatoshi, toAddress, memo)
|
||||
val transactionId = wallet.createSpend(zatoshi, toAddress, memo)
|
||||
val transaction = repository.findTransactionById(transactionId)
|
||||
?: throw TransactionNotFoundException(transactionId)
|
||||
EncodedTransaction(transaction.transactionId, transaction.raw
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package cash.z.wallet.sdk.exception
|
||||
|
||||
import java.lang.Exception
|
||||
import java.lang.RuntimeException
|
||||
|
||||
/**
|
||||
* Exceptions thrown in the Rust layer of the SDK. We may not always be able to surface details about this
|
||||
* exception so it's important for the SDK to provide helpful messages whenever these errors are encountered.
|
||||
|
@ -19,8 +16,9 @@ sealed class RepositoryException(message: String, cause: Throwable? = null) : Ru
|
|||
}
|
||||
|
||||
sealed class SynchronizerException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
||||
object FalseStart: SynchronizerException("Once a synchronizer has stopped it cannot be restarted. Instead, a new " +
|
||||
"instance should be created.")
|
||||
object FalseStart: SynchronizerException("This synchronizer was already started. Multiple calls to start are not" +
|
||||
"allowed and once a synchronizer has stopped it cannot be restarted."
|
||||
)
|
||||
}
|
||||
|
||||
sealed class CompactBlockProcessorException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) {
|
||||
|
|
|
@ -2,13 +2,10 @@ package cash.z.wallet.sdk.ext
|
|||
|
||||
import android.content.Context
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
import kotlinx.coroutines.delay
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
|
||||
inline fun Int.toBlockHeight(): Service.BlockID = Service.BlockID.newBuilder().setHeight(this.toLong()).build()
|
||||
|
||||
suspend inline fun retryUpTo(retries: Int, initialDelay: Int = 10, block: () -> Unit) {
|
||||
var failedAttempts = 0
|
||||
while (failedAttempts < retries) {
|
||||
|
|
|
@ -67,4 +67,9 @@ const val DEFAULT_REWIND_DISTANCE = 10
|
|||
* The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
|
||||
* returning from the background and is exposed via the Synchronizer's isStale function.
|
||||
*/
|
||||
const val DEFAULT_STALE_TOLERANCE = 10
|
||||
const val DEFAULT_STALE_TOLERANCE = 10
|
||||
|
||||
/**
|
||||
* The default port to use for connecting to lightwalletd instances.
|
||||
*/
|
||||
const val DEFAULT_LIGHTWALLETD_PORT = 9067
|
|
@ -9,49 +9,49 @@ import cash.z.wallet.sdk.data.twig
|
|||
*/
|
||||
class RustBackend : RustBackendWelding {
|
||||
|
||||
external override fun initDataDb(dbData: String): Boolean
|
||||
external override fun initDataDb(dbDataPath: String): Boolean
|
||||
|
||||
external override fun initAccountsTable(
|
||||
dbData: String,
|
||||
dbDataPath: String,
|
||||
seed: ByteArray,
|
||||
accounts: Int): Array<String>
|
||||
|
||||
external override fun initBlocksTable(
|
||||
dbData: String,
|
||||
dbDataPath: String,
|
||||
height: Int,
|
||||
hash: String,
|
||||
time: Long,
|
||||
saplingTree: String): Boolean
|
||||
|
||||
external override fun getAddress(dbData: String, account: Int): String
|
||||
external override fun getAddress(dbDataPath: String, account: Int): String
|
||||
|
||||
external override fun isValidShieldedAddress(addr: String): Boolean
|
||||
|
||||
external override fun isValidTransparentAddress(addr: String): Boolean
|
||||
|
||||
external override fun getBalance(dbData: String, account: Int): Long
|
||||
external override fun getBalance(dbDataPath: String, account: Int): Long
|
||||
|
||||
external override fun getVerifiedBalance(dbData: String, account: Int): Long
|
||||
external override fun getVerifiedBalance(dbDataPath: String, account: Int): Long
|
||||
|
||||
external override fun getReceivedMemoAsUtf8(dbData: String, idNote: Long): String
|
||||
external override fun getReceivedMemoAsUtf8(dbDataPath: String, idNote: Long): String
|
||||
|
||||
external override fun getSentMemoAsUtf8(dbData: String, idNote: Long): String
|
||||
external override fun getSentMemoAsUtf8(dbDataPath: String, idNote: Long): String
|
||||
|
||||
external override fun validateCombinedChain(db_cache: String, db_data: String): Int
|
||||
external override fun validateCombinedChain(dbCachePath: String, dbDataPath: String): Int
|
||||
|
||||
external override fun rewindToHeight(db_data: String, height: Int): Boolean
|
||||
external override fun rewindToHeight(dbDataPath: String, height: Int): Boolean
|
||||
|
||||
external override fun scanBlocks(db_cache: String, db_data: String): Boolean
|
||||
external override fun scanBlocks(dbCachePath: String, dbDataPath: String): Boolean
|
||||
|
||||
external override fun sendToAddress(
|
||||
dbData: String,
|
||||
external override fun createToAddress(
|
||||
dbDataPath: String,
|
||||
account: Int,
|
||||
extsk: String,
|
||||
to: String,
|
||||
value: Long,
|
||||
memo: String,
|
||||
spendParams: String,
|
||||
outputParams: String
|
||||
spendParamsPath: String,
|
||||
outputParamsPath: String
|
||||
): Long
|
||||
|
||||
external override fun initLogs()
|
||||
|
|
|
@ -6,49 +6,49 @@ package cash.z.wallet.sdk.jni
|
|||
*/
|
||||
interface RustBackendWelding {
|
||||
|
||||
fun initDataDb(dbData: String): Boolean
|
||||
fun initDataDb(dbDataPath: String): Boolean
|
||||
|
||||
fun initAccountsTable(
|
||||
dbData: String,
|
||||
dbDataPath: String,
|
||||
seed: ByteArray,
|
||||
accounts: Int): Array<String>
|
||||
|
||||
fun initBlocksTable(
|
||||
dbData: String,
|
||||
dbDataPath: String,
|
||||
height: Int,
|
||||
hash: String,
|
||||
time: Long,
|
||||
saplingTree: String): Boolean
|
||||
|
||||
fun getAddress(dbData: String, account: Int): String
|
||||
fun getAddress(dbDataPath: String, account: Int): String
|
||||
|
||||
fun isValidShieldedAddress(addr: String): Boolean
|
||||
|
||||
fun isValidTransparentAddress(addr: String): Boolean
|
||||
|
||||
fun getBalance(dbData: String, account: Int): Long
|
||||
fun getBalance(dbDataPath: String, account: Int): Long
|
||||
|
||||
fun getVerifiedBalance(dbData: String, account: Int): Long
|
||||
fun getVerifiedBalance(dbDataPath: String, account: Int): Long
|
||||
|
||||
fun getReceivedMemoAsUtf8(dbData: String, idNote: Long): String
|
||||
fun getReceivedMemoAsUtf8(dbDataPath: String, idNote: Long): String
|
||||
|
||||
fun getSentMemoAsUtf8(dbData: String, idNote: Long): String
|
||||
fun getSentMemoAsUtf8(dbDataPath: String, idNote: Long): String
|
||||
|
||||
fun validateCombinedChain(db_cache: String, db_data: String): Int
|
||||
fun validateCombinedChain(dbCachePath: String, dbDataPath: String): Int
|
||||
|
||||
fun rewindToHeight(db_data: String, height: Int): Boolean
|
||||
fun rewindToHeight(dbDataPath: String, height: Int): Boolean
|
||||
|
||||
fun scanBlocks(db_cache: String, db_data: String): Boolean
|
||||
fun scanBlocks(dbCachePath: String, dbDataPath: String): Boolean
|
||||
|
||||
fun sendToAddress(
|
||||
dbData: String,
|
||||
fun createToAddress(
|
||||
dbDataPath: String,
|
||||
account: Int,
|
||||
extsk: String,
|
||||
to: String,
|
||||
value: Long,
|
||||
memo: String,
|
||||
spendParams: String,
|
||||
outputParams: String
|
||||
spendParamsPath: String,
|
||||
outputParamsPath: String
|
||||
): Long
|
||||
|
||||
fun initLogs()
|
||||
|
|
|
@ -138,40 +138,45 @@ class Wallet(
|
|||
}
|
||||
|
||||
/**
|
||||
* Does the proofs and processing required to create a raw transaction and inserts the result in the database. On
|
||||
* average, this call takes over 10 seconds.
|
||||
* Does the proofs and processing required to create a transaction to spend funds and inserts
|
||||
* the result in the database. On average, this call takes over 10 seconds.
|
||||
*
|
||||
* @param value the zatoshi value to send
|
||||
* @param toAddress the destination address
|
||||
* @param memo the memo, which is not augmented in any way
|
||||
*
|
||||
* @return the row id in the transactions table that contains the raw transaction or -1 if it failed
|
||||
* @return the row id in the transactions table that contains the spend transaction
|
||||
* or -1 if it failed
|
||||
*/
|
||||
suspend fun createRawSendTransaction(value: Long, toAddress: String, memo: String = "", fromAccountId: Int = accountIds[0]): Long =
|
||||
withContext(IO) {
|
||||
twigTask("creating raw transaction to send $value zatoshi to ${toAddress.masked()} with memo $memo") {
|
||||
try {
|
||||
ensureParams(paramDestinationDir)
|
||||
twig("params exist at $paramDestinationDir! attempting to send...")
|
||||
rustBackend.sendToAddress(
|
||||
dataDbPath,
|
||||
fromAccountId,
|
||||
spendingKeyStore,
|
||||
toAddress,
|
||||
value,
|
||||
memo,
|
||||
// using names here so it's easier to avoid transposing them, if the function signature changes
|
||||
spendParams = SPEND_PARAM_FILE_NAME.toPath(),
|
||||
outputParams = OUTPUT_PARAM_FILE_NAME.toPath()
|
||||
)
|
||||
} catch (t: Throwable) {
|
||||
twig("${t.message}")
|
||||
throw t
|
||||
}
|
||||
}.also { result ->
|
||||
twig("result of sendToAddress: $result")
|
||||
suspend fun createSpend(
|
||||
value: Long,
|
||||
toAddress: String,
|
||||
memo: String = "",
|
||||
fromAccountId: Int = accountIds[0]
|
||||
): Long = withContext(IO) {
|
||||
twigTask("creating transaction to spend $value zatoshi to ${toAddress.masked()} with memo $memo") {
|
||||
try {
|
||||
ensureParams(paramDestinationDir)
|
||||
twig("params exist at $paramDestinationDir! attempting to send...")
|
||||
rustBackend.createToAddress(
|
||||
dataDbPath,
|
||||
fromAccountId,
|
||||
spendingKeyStore,
|
||||
toAddress,
|
||||
value,
|
||||
memo,
|
||||
// using names here so it's easier to avoid transposing them, if the function signature changes
|
||||
spendParamsPath = SPEND_PARAM_FILE_NAME.toPath(),
|
||||
outputParamsPath = OUTPUT_PARAM_FILE_NAME.toPath()
|
||||
)
|
||||
} catch (t: Throwable) {
|
||||
twig("${t.message}")
|
||||
throw t
|
||||
}
|
||||
}.also { result ->
|
||||
twig("result of sendToAddress: $result")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and store the params into the given directory.
|
||||
|
@ -284,8 +289,8 @@ class Wallet(
|
|||
* @return a WalletBirthday that reflects the contents of the file or an exception when parsing fails.
|
||||
*/
|
||||
fun loadBirthdayFromAssets(context: Context, birthdayHeight: Int? = null): WalletBirthday {
|
||||
val treeFiles = context.assets.list(Wallet.BIRTHDAY_DIRECTORY).apply { sortDescending() }
|
||||
if (treeFiles.isEmpty()) throw WalletException.MissingBirthdayFilesException(BIRTHDAY_DIRECTORY)
|
||||
val treeFiles = context.assets.list(Wallet.BIRTHDAY_DIRECTORY)?.apply { sortDescending() }
|
||||
if (treeFiles.isNullOrEmpty()) throw WalletException.MissingBirthdayFilesException(BIRTHDAY_DIRECTORY)
|
||||
try {
|
||||
val file = treeFiles.first {
|
||||
if (birthdayHeight == null) true
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package cash.z.wallet.sdk.service
|
||||
|
||||
import android.content.Context
|
||||
import cash.z.wallet.sdk.R
|
||||
import cash.z.wallet.sdk.entity.CompactBlock
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import cash.z.wallet.sdk.exception.LightwalletException
|
||||
import cash.z.wallet.sdk.ext.DEFAULT_LIGHTWALLETD_PORT
|
||||
import cash.z.wallet.sdk.rpc.CompactFormats
|
||||
import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
|
@ -12,8 +14,20 @@ import io.grpc.ManagedChannel
|
|||
import io.grpc.android.AndroidChannelBuilder
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class LightWalletGrpcService private constructor(private val channel: ManagedChannel)
|
||||
: LightWalletService {
|
||||
/**
|
||||
* Implementation of LightwalletService using gRPC for requests to lightwalletd.
|
||||
*
|
||||
* @param channel the channel to use for communicating with the lightwalletd server.
|
||||
* @param singleRequestTimeoutSec the timeout to use for non-streaming requests. When a new stub is
|
||||
* created, it will use a deadline that is after the given duration from now.
|
||||
* @param streamingRequestTimeoutSec the timeout to use for streaming requests. When a new stub is
|
||||
* created for streaming requests, it will use a deadline that is after the given duration from now.
|
||||
*/
|
||||
class LightWalletGrpcService private constructor(
|
||||
private val channel: ManagedChannel,
|
||||
private val singleRequestTimeoutSec: Long = 10L,
|
||||
private val streamingRequestTimeoutSec: Long = 90L
|
||||
) : LightWalletService {
|
||||
|
||||
constructor(
|
||||
appContext: Context,
|
||||
|
@ -26,12 +40,12 @@ class LightWalletGrpcService private constructor(private val channel: ManagedCha
|
|||
|
||||
override fun getBlockRange(heightRange: IntRange): List<CompactBlock> {
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub(90L).getBlockRange(heightRange.toBlockRange()).toList()
|
||||
return channel.createStub(streamingRequestTimeoutSec).getBlockRange(heightRange.toBlockRange()).toList()
|
||||
}
|
||||
|
||||
override fun getLatestBlockHeight(): Int {
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub(10L).getLatestBlock(Service.ChainSpec.newBuilder().build()).height.toInt()
|
||||
return channel.createStub(singleRequestTimeoutSec).getLatestBlock(Service.ChainSpec.newBuilder().build()).height.toInt()
|
||||
}
|
||||
|
||||
override fun submitTransaction(raw: ByteArray): Service.SendResponse {
|
||||
|
@ -50,7 +64,9 @@ class LightWalletGrpcService private constructor(private val channel: ManagedCha
|
|||
.newBlockingStub(this)
|
||||
.withDeadlineAfter(timeoutSec, TimeUnit.SECONDS)
|
||||
|
||||
private fun IntRange.toBlockRange(): Service.BlockRange =
|
||||
private inline fun Int.toBlockHeight(): Service.BlockID = Service.BlockID.newBuilder().setHeight(this.toLong()).build()
|
||||
|
||||
private inline fun IntRange.toBlockRange(): Service.BlockRange =
|
||||
Service.BlockRange.newBuilder()
|
||||
.setStart(this.first.toBlockHeight())
|
||||
.setEnd(this.last.toBlockHeight())
|
||||
|
|
|
@ -373,7 +373,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_scanBlocks(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_sendToAddress(
|
||||
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_createToAddress(
|
||||
env: JNIEnv<'_>,
|
||||
_: JClass<'_>,
|
||||
db_data: JString<'_>,
|
||||
|
@ -396,7 +396,7 @@ pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_RustBackend_sendToAddress(
|
|||
let to = utils::java_string_to_rust(&env, to);
|
||||
let value = Amount::from_i64(value).map_err(|()| format_err!("Invalid amount, out of range"))?;
|
||||
if value.is_negative() {
|
||||
return Err(ormat_err!("Amount is negative"));
|
||||
return Err(format_err!("Amount is negative"));
|
||||
}
|
||||
let memo = utils::java_string_to_rust(&env, memo);
|
||||
let spend_params = utils::java_string_to_rust(&env, spend_params);
|
||||
|
|
|
@ -72,12 +72,12 @@ fn throw(env: &JNIEnv, description: &str) {
|
|||
}
|
||||
|
||||
// Tries to get meaningful description from panic-error.
|
||||
pub fn any_to_string(any: &Box<Any + Send>) -> String {
|
||||
pub fn any_to_string(any: &Box<dyn Any + Send>) -> String {
|
||||
if let Some(s) = any.downcast_ref::<&str>() {
|
||||
s.to_string()
|
||||
} else if let Some(s) = any.downcast_ref::<String>() {
|
||||
s.clone()
|
||||
} else if let Some(error) = any.downcast_ref::<Box<std::error::Error + Send>>() {
|
||||
} else if let Some(error) = any.downcast_ref::<Box<dyn std::error::Error + Send>>() {
|
||||
error.description().to_string()
|
||||
} else {
|
||||
"Unknown error occurred".to_string()
|
||||
|
|
Loading…
Reference in New Issue