Closes#1012
- This is the first change for the dependency injection. This change
adds `DIContainer` which is used to register and resolve dependencies.
- Then this change shows how `DIContainer` can be used to resolve
dependencies. And it also shows how to mock dependencies in tests.
- Constructors of `Initializer` are changed to support mocking of
depedendencies. But it doesn't affect public API in any way.
- Depedencies are registered in `Dependencies.setup()`. Then in the code
`container.resolve(SomeType.self)` is called to get instance of the
dependency.
- `ZcashTestCase` class is added. It inherits from `XCTestCase` and
should be used for base class in tests. `ZcashTestCase` takes care of
creation of `DIContainer` for dependencies mocking. In future we can
maybe move there more things that are used in each test.
- Lot is missing here. Not all the code is using dependency injection.
Tests for `DIContainer` are missing. Only `OfflineTests` work now
(other tests can't be even compiled). It will be added in future
changes.
- `BlockDownloaderImpl` is changed. It now spawns detached Task to
download blocks. So blocks can be downloaded in parallel with scanning
process.
- `Synchronizer.stop()` is no longer async.
- Blocks cache cleaning is changed. It's not possible to drop the whole
cache now. There are some blocks pre-downloaded which weren't scanned
yet.
This PR introduces `ZcashError` enum. This enum represents any error
that can be thrown inside of the SDK and outside of the SDK. Also
`ZcashError` is used in `LightWalletGRPCService` and handled in
`CompactBlockProcessor` as example.
Why enum? First I tried this with some structure which contained code,
message and underlyingError. Problem was when some specific place in the
SDK would like to attach some additional data to error. I didn't want to
add some generic dictionary to store anything with the error.
So I used enum to identify error. Each member can have specified amount
of associated values. So specific error can bring some context data. And
it's type safe.
Each error has also a code. Relationship between errors and codes is
1:1. It may looks bit redundant but it's important. The client app now
can choose how to process errors. Either identify those by the error
itself or by code.
Definition or errors and codes is in `ZcashErrorDefinition`. And then
`ZcashError` and `ZcashErrorCode` are generated by Sourcery. Thanks to
this it is easier to maintain the final code. And it gives us ability to
generate any kind of documentation for the errors and codes. I created
simple example of this in this PR. And it doesn't make the SDK
completely dependent on the Sourcery. Final structures aren't super
complicated and can be written manually if needed.
[#923] Update error handling in DatabaseStorageManager.swift
- cleanup of DatabaseStorageManager, not used anymore
- ZcashError for SimpleConnectionProvider
Revert "[#923] Update error handling in DatabaseStorageManager.swift"
This reverts commit 94e028d31a.
Fix script which generates ZcashError
[#922] Update error handling in DatabaseMigrationManager.swift
Closes#922
[#923] Update error handling in DatabaseStorageManager.swift
- The DatabaseStorageManager is not used so I deleted it
- SimpleConnectionProvider's errors updated
Fix tests
[#955] Update error handling in SaplingParameterDownloader
Closes#955
[#936] Update error handling in NotesDao
Closes#936
[#935] Update error handling in BlockDao
Closes#935
[#931] InternalSyncProgress.computeNextState doesn't need to throw
Closes#931
[#950] Update error handling in rust backend
Closes#949Closes#950
[#941] Update error handling in AccountEntity
Closes#941
[#928] Update error handling in FSCompactBlockRepository
Closes#928
[#925] Update error handling in BlockDownloaderService (#974)
- BlockDownloaderService errors updated
[#924] Update error handling in BlockDownloader (#973)
- BlockDownloaderStream nextBlock updated
[#942] Update error handling in TransactionEntity (#977)
- ZcashTransaction init errors converted to the ZcashError
[#939] Update error handling in TransactionDao (#976)
- TransactionRepositoryError removed and replaced with ZcashError
- all TransactionDAO errors converted to ZcashError
[#943] Update error handling in ZcashCompactBlock
Closes#943
[#945] Update error handling in Memo
Closes#945
[#934] Update error handling in Checkpoint
Closes#944Closes#934
[#938] Update error handling in PendingTransactionDao
Closes#938
[#926] Update error handling in BlockEnhancer
- WIP, switching to transaction repository to unblock this ticket
[#926] Update error handling in BlockEnhancer
- enhancer's errors done
[#926] Update error handling in BlockEnhancer (#994)
- cleanup
[#952] Update error handling in DerivationTool
Closes#952
[#932] Update error handling in BlockValidator
Closes#932
[#940] Update error handling in UnspentTransactionOutputDao
Closes#940
[#946] Update error handling in WalletTypes
Closes#946
[#954] Update error handling in WalletTransactionEncoder
Closes#954
[#953] Update error handling in PersistentTransactionManager
Closes#953
[#956] Update error handling in Initializer
Closes#956
[#947] Update error handling in Zatoshi (#996)
- Zatoshi's errors converted to ZcashError
[#927] Update error handling in UTXOFetcher (#997)
- UTXOFetcher resolved
Use let instead of var where applicable
In the SDK `var` was used on places where `let` would be sufficient. And
default strategy in Swift should use use `let` until mutability is
required. So all these places are changed. No logic is changed.
[#933] Update error handling in CompactBlockProcessor
- CompactBlockProcessor's errors refactored to ZcashError
[#933] Update error handling in CompactBlockProcessor #999
- comments addressed
[#951] Update error handling in SDKSynchronizer
- SDKSynchronizer's errors refactored to ZcashError
[#951] Update error handling in SDKSynchronizer (#1002)
- comments resolved
Make DerivationTool constructor public
DerivationTool.init should be public. This was removed by accident when
adopting async.
[#361] Add changelog
- attached to the processor's timer
- added latest scanned time and latest block height
- sample app showing the new values alongside with the %
- unit tests fixed
- latestBlock() API added
- the transaction repository is no longer used to update the exposed values during the syncing
Closes#888.
- `ZcashRustBackend` is actor now. So majority of methods in this actor
are now async.
- Some methods stayed `static` in `ZcashRustBackend`. It would be hard
to pass instance of the `ZcashRustBackend` to the places where these
methods are used in static manner. And it would change lot of APIs.
But it isn't problem from technical perspective because these methods
would be `nonisolated` otherwise.
- Methods `lastError()` and `getLastError()` in `ZcashRustBackend` are
now private. This makes sure that ther won't be aby race condition
between other methods and these two error methods.
- All the methods for which was `lastError()` used in code now throw
error. So `lastError()` is no longer needed outside of the
`ZcashRustBackend`.
- There are in the public API related to `DerivationTool`.
- `DerivationTool` now requires instance of the `ZcashRustBackend`. And
`ZcashRustBackend` isn't public type. So `DerivationTool` doesn't have
any public constructor now. It can be created only via
`Initializer.makeDerivationTool()` instance method.
- `deriveUnifiedSpendingKey()` and `deriveUnifiedFullViewingKey()` in
`DerivationTool` are now async. It is because these are using
`ZcashRustBackend` inside. `DerivationTool` offers alternative
(closure and combine) APIs. But downside is that there is no sync API
to dervie spending key or viewing key.
- Some methods of the `DerivationTool` are now static. These methods
don't use anything that requires instance of the `DerivationTool`
inside.
[#888] Use Sourcery to generate mocks
- I wrote mock for `Synchronizer` manually. And it's tedious and long
and boring work.
- Now `ZcashRustBackendWelding` is changed a lot so it means
`MockRustBackend` must be changed a lot. So I decided to introduce
`sourcery` to generate mocks from protocols so we don't have to do it
manually ever.
- To generate mocks go to `ZcashLightClientKit/Tests/TestUtils/Sourcery`
directory and run `generateMocks.sh` script.
- Your protocol must be mentioned in `AutoMockable.swift` file.
Generated mocks are in `AutoMockable.generated.swift` file.
[#888] Fix Offline tests
- Offline tests target now runs and tests are green.
- There is log of changes in tests. But logic is not changed.
- Updated `AutoMockable.stencil` so sourcery is able to generate mock as
actor when protocol is marked with: `// sourcery: mockActor`.
- Last few updates in `ZcashRustBackendWelding`. In previous PR `rewindCacheToHeight`
methods was overlooked and it didn't throw error.
- Removed `MockRustBackend` and using generated
`ZCashRustBackendWeldingMock` instead.
- Using generated `SynchronizerMock`.
[#888] Fix NetworkTests
- Changed a bit how rust backend mock is used in the tests. Introduced
`RustBackendMockHelper`. There are some state variables that must be
preserved within one instance of the mock. This helper does exactly
this. It keeps this state variables in the memory and helping mock to
work as expected.
[#888] Fix Darkside tests
Create ZcashKeyDeriving internal protocol
Use New DerivationTool that does not require RustBackend
Remove duplicated methods that had been copied over
[#888] Fix potentially broken tests
I broke the tests because I moved `testTempDirectory` from each
`TestCase` to the `Environment`. By this I caused that each tests uses
exactly same URL. Which is directly against purpose of
`testTempDirectory`.
So now each test calls this one and store it to local variable. So each
test has unique URL.
[#888] Add ability to mock nonisolated methods to AutoMockable.stencil
[#888] Add changelog and fix the documentation in ZcashRustBackendWelding
[#888] Rename derivation rust backend protocol and remove static methods
- Renamed `ZcashKeyDeriving` to `ZcashKeyDerivationBackendWelding`. So
the naming scheme is same as for `ZcashRustBackendWelding`.
- `ZcashKeyDerivationBackend` is now struct instead of enum.
- Methods in `ZcashKeyDerivationBackendWelding` (except one) are no
longer static. Because of this the respective methods in
`DerivationTool` aren't also static anymore.
Closes#895
Add Sync Session ID to `SynchronizerState`.
A SyncSession is an attempt to sync the blockchain within the lifetime of a Synchronizer.
A Synchronizer can sync many times, when synced it will refresh every ~20 seconds +- random padding.
each sync attempt will have a different UUID even if it's from the same instance of SDKSynchronizer.
**How are SyncSessions are delimited? With `SyncStatus` changes.**
changes from [`.unprepared`|`.error`|`.disconnected`|`.stopped`] to `.syncing` assign a new sessionID to the synchronizer.
Any other transitions won't.
`areTwoStatusesDifferent ` was refactored to a helper function of `SyncStatus`
**How are IDs generated?**
ID generation is not mandated but delegated to a protocol `SyncSessionIDGenerator`.
Tests inject their own deterministic generator to avoid test flakiness.
Default implementation of SyncSessionIDGenerator is
````Swift
struct UniqueSyncSessionIDGenerator {}
extension UniqueSyncSessionIDGenerator: SyncSessionIDGenerator {
func nextID() -> UUID {
UUID()
}
}
````
**SyncSession Pseudo-Atomicity and thread safety**
SyncSession is a type alias of a GenericActor holding a UUID
````
typealias SyncSession = GenericActor<UUID>
extension SyncSession {
/// updates the current sync session to a new value with the given generator
/// - Parameters generator: a `SyncSessionIDGenerator`
/// - returns: the `UUID` of the newly updated value.
@discardableResult
func newSession(with generator: SyncSessionIDGenerator) async -> UUID {
return await self.update(generator.nextID())
}
}
````
Closes#895
SessionTicker struct to control session transitions.
switching to `.unprepared` now makes syncID to be `.nullID`
Closes#209.
[#845] Introduce ZcashSynchronizerAlias enum
Closes#845.
[#852] SDKSynchronizer using queues label based on the alias
Closes#852.
[#847] Remove posibility to use DatabaseStorageManager as singleton
Closes#847.
[#850] Remove synchronizerConnectionStateChanged notification
Closes#850.
[#855] Add check if the Alias is already used
Closes#855
- Added `UsedAliasesChecker` utility which is used to register aliases
that are in use.
- `prepare()` and `wipe()` methods now check if the current alias can't
be used and if not then `InitializerError.aliasAlreadyInUse` is
thrown/emitted.
- Some public methods that could cause harm if used with the Alias that
is already in use now throw `SynchronizerError.notPrepared`. Thanks to
this the client app is forced to call `prepare()` first. And
`prepare()` does check for the Alias.
- Added tests for new conditions.
[#849] Make InternalSyncProgress aware of the Alias
Closes#849.
[#853] Only instance with default Alias migrates legacy cache DB
Closes#853.
[#851] Apply the Alias to the URLs
Closes#851.
- `Initializer` now updates paths according to alias before paths are
used anywhere in the SDK.
- Paths update can fail. It would be incovenient for the client apps to
handle errors thrown from `Initiliazer` constructor. So the error is
then handled in `SDKSynchronizer.prepare()` or `SDKSynchronizer.wipe()`.
[#846] Stop using SDKMetrics as singleton (#862)
- metrics are not longer a singleton
- tests fixed
- metrics outside init of the synchronizer
[#848] Make logger aware of the alias
- logger is now an instance passed throughout the sdk instead of a static proxy
[#848] Make logger aware of the alias (#868)
- comments addressed
[#848] Make logger aware of the alias (#868)
- returning protocol back
Fix typos
[#856] Add possibility to test multiple synchronizers in the sample app
Closes#856.
- Added `alias` property to `Synchronizer`.
- Added `SyncBlocksListViewController` which provides UI to use multiple
synchronizers at once.
[#209] Add changelog
- Add changelog for #209.
- Overall improve readability of the rendered changelog. Tickets
references are now prefixed with `###` instead of `- `.
Fix compilation
This change introduces two new protocols: `ClosureSynchronizer` and
`CombineSynchronizer`. These two protocols define API that doesn't use
`async`. So the client can choose exactly which API it wants to use.
This change also introduces two new objects: `ClosureSDKSynchronizer`
and `CombineSDKSynchronizer`. These two implement the respective protocols
mentioned above. Both are structures. Neither of these two keeps any state.
Thanks to this each is very cheap to create. And usage of these two isn't
mutually exclusive. So devs can really choose the best SDK API for each
part of the client app.
[#831] Use async inside of the SDKSynchronizer
- In general lot of methods inside the `SDKSynchronizer` and
`CompactBlockProcessoer` which weren't async are now async. And other
changes are made because of this change.
- `CompactBlockProcessor` no longer uses Combine to communicate with
`SDKSynchronizer`. Reason for this is that Combine doesn't play great
with async. Closure passed to `sink` isn't async.
- Because of this and because of how our tests work (receiving signals
from CBP directly) `CompactBlockProcessor` must be able to handle more
event closures. Not just one. So it now has `eventClosures`
dictionary. It's little bit strange but it works fine.
- `SyncStatus` inside the `SDKSynchronizer` was previously protected by
lock. Now it's protected by simple actor wrapper.
- Changes in tests are minimal. Changes were mady only because
`CompactBlockProcessor` changes from Combine to closures.
[#831] Add tests for ClosureSDKSynchronizer
- Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly
calling `Synchronizer` and if the values are correctly returned.
- `ClosuresSDKSynchronizer` doesn't contain any logic but it is public
API and we should be sure that it works correctly.
[#831] Add tests for CombineSDKSynchronizer
[#831] Add changelog
- This is necessary to finish https://github.com/zcash/secant-ios-wallet/issues/529.
The Secant has special log method for logging tca stuff. And this
method will be in extension of `OSLogger` and it needs to access
`oslog`.
Closes#795
- Added structure `SaplingParamsSourceURL` which holds source URLs for
sapling-spend file and sapling-output file. URLs are ultimately passed
to `SaplingParameterDownloader`.
- This is done so it's possible to pass different URLs when running
tests.
- sapling-spend file and sapling-output file are in tests bundle. And
when running tests these files are loaded from bundle and not from
network.
Our main dependency, Swift-GRPC is dropping support for Cocoapods from version 1.8.2.
Even though they make a great work at maintaining backwards compatibility, we will eventually be forced to drop Cocoapods support.
We've reached out partners like NighthawkApps, Horizontal Systems (Unstoppable) and Edge, who have reported not depending on Cocoapods.
We intend to end Cocoapods support on 0.18.0.
Closes#612
- sync process enhanced to try to download sapling params if needed
- tests fixed
- failing import Crypto -> import CryptoKit
- download params only if there are sapling funds
- sendToAddress and SaplingParameterDownloader refactored to async
- unit tests WIP
[486] sendToAddress async/await
- testing code cleanup
[#486] sendToAddress async/await
- reducing number of Tasks in Sample app
[#486] sendToAddress async/await
- I finally figure out how to make the dark side tests async, using new sendToAddress APIs and pass, POC done, 18 more tests to refactor
[#486] sendToAddress async/await
- async sendToAddress unit test refactored except NetworkUpgradeTests
[#486] sendToAddress async/await
- NetworkUpgradeTests refactored to async API
[#486] sendToAddress async/await
- cleanup
[#486] sendToAddress async/await (#536)
- PR comments resolved
Closes#381
This commit brings a Zatoshi type developed on the Secant project,
helper classes like Clamped and tests.
Zatoshi has been incorporated as a Codable type for SQLite Swift
to allow serialization into the pending database.
FIXES on Demo App
fix comments
Closes#326
Implements loading checkpoints from the bundle the same way the android SDK does.
* Add checkpoint files
* Add checkpoint files as resources to package
* Remove stencil files
* Update wallet birthday methods to use bundled checkpoints
* [clean up] Fix test build failure
* Add Cocoapods support
* Fix for behaviour across SPM and Cocoapods
* Add test for checkpoint retrieval
* Use latest GRPC v1.x
* update checkpoint files to match android sdk