react-native-zcash 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +7 -3
  3. package/android/build.gradle +5 -4
  4. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2240000.json +8 -0
  5. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2250000.json +8 -0
  6. package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +221 -169
  7. package/android/src/main/java/app/edge/rnzcash/RNZcashPackage.kt +1 -2
  8. package/ios/RNZcash.m +5 -8
  9. package/ios/RNZcash.swift +177 -137
  10. package/ios/ZCashLightClientKit/Block/Actions/Action.swift +98 -0
  11. package/ios/ZCashLightClientKit/Block/Actions/ClearAlreadyScannedBlocksAction.swift +35 -0
  12. package/ios/ZCashLightClientKit/Block/Actions/ClearCacheAction.swift +30 -0
  13. package/ios/ZCashLightClientKit/Block/Actions/DownloadAction.swift +67 -0
  14. package/ios/ZCashLightClientKit/Block/Actions/EnhanceAction.swift +97 -0
  15. package/ios/ZCashLightClientKit/Block/Actions/FetchUTXOsAction.swift +33 -0
  16. package/ios/ZCashLightClientKit/Block/Actions/MigrateLegacyCacheDBAction.swift +70 -0
  17. package/ios/ZCashLightClientKit/Block/Actions/ProcessSuggestedScanRangesAction.swift +59 -0
  18. package/ios/ZCashLightClientKit/Block/Actions/RewindAction.swift +48 -0
  19. package/ios/ZCashLightClientKit/Block/Actions/SaplingParamsAction.swift +33 -0
  20. package/ios/ZCashLightClientKit/Block/Actions/ScanAction.swift +95 -0
  21. package/ios/ZCashLightClientKit/Block/Actions/UpdateChainTipAction.swift +55 -0
  22. package/ios/ZCashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +58 -0
  23. package/ios/ZCashLightClientKit/Block/Actions/ValidateServerAction.swift +60 -0
  24. package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +421 -937
  25. package/ios/ZCashLightClientKit/Block/Download/BlockDownloader.swift +31 -17
  26. package/ios/ZCashLightClientKit/Block/Download/BlockDownloaderService.swift +2 -2
  27. package/ios/ZCashLightClientKit/Block/Enhance/BlockEnhancer.swift +46 -15
  28. package/ios/ZCashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +4 -15
  29. package/ios/ZCashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift +4 -4
  30. package/ios/ZCashLightClientKit/Block/Scan/BlockScanner.swift +10 -35
  31. package/ios/ZCashLightClientKit/Block/Utils/CompactBlockProgress.swift +24 -0
  32. package/ios/ZCashLightClientKit/Block/Utils/SyncControlData.swift +25 -0
  33. package/ios/ZCashLightClientKit/ClosureSynchronizer.swift +1 -2
  34. package/ios/ZCashLightClientKit/CombineSynchronizer.swift +2 -5
  35. package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +7 -25
  36. package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +40 -42
  37. package/ios/ZCashLightClientKit/DAO/UnspentTransactionOutputDao.swift +13 -4
  38. package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +9 -0
  39. package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +7 -10
  40. package/ios/ZCashLightClientKit/Error/Sourcery/generateErrorCode.sh +1 -1
  41. package/ios/ZCashLightClientKit/Error/ZcashError.swift +121 -12
  42. package/ios/ZCashLightClientKit/Error/ZcashErrorCode.swift +43 -5
  43. package/ios/ZCashLightClientKit/Error/ZcashErrorCodeDefinition.swift +72 -6
  44. package/ios/ZCashLightClientKit/Extensions/Bool+ToData.swift +15 -0
  45. package/ios/ZCashLightClientKit/Extensions/Data+ToOtherTypes.swift +18 -0
  46. package/ios/ZCashLightClientKit/Extensions/Int+ToData.swift +15 -0
  47. package/ios/ZCashLightClientKit/Initializer.swift +47 -26
  48. package/ios/ZCashLightClientKit/Metrics/SDKMetrics.swift +0 -12
  49. package/ios/ZCashLightClientKit/Model/Checkpoint.swift +12 -0
  50. package/ios/ZCashLightClientKit/Model/ScanProgress.swift +29 -0
  51. package/ios/ZCashLightClientKit/Model/ScanRange.swift +31 -0
  52. package/ios/ZCashLightClientKit/Modules/Service/GRPC/LightWalletGRPCService.swift +15 -0
  53. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift +150 -46
  54. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto +30 -16
  55. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto +32 -6
  56. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift +259 -22
  57. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift +193 -7
  58. package/ios/ZCashLightClientKit/Modules/Service/LightWalletService.swift +8 -0
  59. package/ios/ZCashLightClientKit/Providers/LatestBlocksDataProvider.swift +18 -28
  60. package/ios/ZCashLightClientKit/Repository/CompactBlockRepository.swift +1 -1
  61. package/ios/ZCashLightClientKit/Repository/TransactionRepository.swift +2 -6
  62. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2092500.json +8 -0
  63. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2095000.json +8 -0
  64. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2097500.json +8 -0
  65. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2102500.json +8 -0
  66. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2105000.json +8 -0
  67. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2107500.json +8 -0
  68. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2112500.json +8 -0
  69. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2115000.json +8 -0
  70. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2117500.json +8 -0
  71. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2122500.json +8 -0
  72. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2125000.json +8 -0
  73. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2127500.json +8 -0
  74. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2132500.json +8 -0
  75. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2135000.json +8 -0
  76. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2137500.json +8 -0
  77. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2142500.json +8 -0
  78. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2145000.json +8 -0
  79. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2147500.json +8 -0
  80. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2152500.json +8 -0
  81. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2155000.json +8 -0
  82. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2157500.json +8 -0
  83. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2162500.json +8 -0
  84. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2165000.json +8 -0
  85. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2167500.json +8 -0
  86. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2172500.json +8 -0
  87. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2175000.json +8 -0
  88. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2177500.json +8 -0
  89. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2182500.json +8 -0
  90. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2185000.json +8 -0
  91. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2187500.json +8 -0
  92. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2192500.json +8 -0
  93. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2195000.json +8 -0
  94. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2197500.json +8 -0
  95. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2202500.json +8 -0
  96. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2205000.json +8 -0
  97. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2207500.json +8 -0
  98. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2212500.json +8 -0
  99. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2215000.json +8 -0
  100. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2217500.json +8 -0
  101. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2222500.json +8 -0
  102. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2225000.json +8 -0
  103. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2227500.json +8 -0
  104. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2230000.json +8 -0
  105. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2232500.json +8 -0
  106. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2235000.json +8 -0
  107. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2237500.json +8 -0
  108. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2240000.json +8 -0
  109. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2242500.json +8 -0
  110. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2245000.json +8 -0
  111. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2247500.json +8 -0
  112. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2250000.json +8 -0
  113. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2350000.json +8 -0
  114. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2360000.json +8 -0
  115. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2370000.json +8 -0
  116. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2380000.json +8 -0
  117. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2390000.json +8 -0
  118. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2400000.json +8 -0
  119. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2410000.json +8 -0
  120. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2420000.json +8 -0
  121. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2430000.json +8 -0
  122. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2440000.json +8 -0
  123. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2450000.json +8 -0
  124. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2460000.json +8 -0
  125. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2470000.json +8 -0
  126. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2480000.json +8 -0
  127. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2490000.json +8 -0
  128. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2500000.json +8 -0
  129. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2510000.json +8 -0
  130. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2520000.json +8 -0
  131. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2530000.json +8 -0
  132. package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +293 -158
  133. package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +58 -64
  134. package/ios/ZCashLightClientKit/Rust/zcashlc.h +618 -512
  135. package/ios/ZCashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +2 -8
  136. package/ios/ZCashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +3 -15
  137. package/ios/ZCashLightClientKit/Synchronizer/Dependencies.swift +11 -30
  138. package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +41 -50
  139. package/ios/ZCashLightClientKit/Synchronizer.swift +51 -65
  140. package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +2 -2
  141. package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +7 -7
  142. package/ios/ZCashLightClientKit/Utils/OSLogger.swift +3 -3
  143. package/ios/ZCashLightClientKit/Utils/ZcashFileManager.swift +16 -0
  144. package/ios/libzcashlc.xcframework/Info.plist +4 -0
  145. package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
  146. package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
  147. package/lib/rnzcash.rn.js +29 -29
  148. package/lib/rnzcash.rn.js.map +1 -1
  149. package/lib/src/react-native.d.ts +5 -5
  150. package/lib/src/types.d.ts +27 -15
  151. package/package.json +2 -1
  152. package/src/react-native.ts +40 -21
  153. package/src/types.ts +36 -24
  154. package/ios/ZCashLightClientKit/Block/Utils/InternalSyncProgress.swift +0 -200
  155. package/ios/ZCashLightClientKit/Block/Validate/BlockValidator.swift +0 -51
  156. package/ios/ZCashLightClientKit/DAO/BlockDao.swift +0 -112
  157. package/ios/ZCashLightClientKit/Entity/BlockProgress.swift +0 -24
@@ -1,4 +1,4 @@
1
- // Generated using Sourcery 2.0.2 — https://github.com/krzysztofzablocki/Sourcery
1
+ // Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery
2
2
  // DO NOT EDIT
3
3
 
4
4
  /*
@@ -9,12 +9,18 @@ error originates. And it can help with debugging.
9
9
  */
10
10
 
11
11
  public enum ZcashErrorCode: String {
12
- /// Some error happened that is not handled as `ZcashError`.
12
+ /// Some error happened that is not handled as `ZcashError`. All errors in the SDK are (should be) `ZcashError`.
13
13
  case unknown = "ZUNKWN0001"
14
14
  /// Updating of paths in `Initilizer` according to alias failed.
15
15
  case initializerCantUpdateURLWithAlias = "ZINIT0001"
16
16
  /// Alias used to create this instance of the `SDKSynchronizer` is already used by other instance.
17
17
  case initializerAliasAlreadyInUse = "ZINIT0002"
18
+ /// Object on disk at `generalStorageURL` path exists. But it file not directory.
19
+ case initializerGeneralStorageExistsButIsFile = "ZINIT0003"
20
+ /// Can't create directory at `generalStorageURL` path.
21
+ case initializerGeneralStorageCantCreate = "ZINIT0004"
22
+ /// Can't set `isExcludedFromBackup` flag to `generalStorageURL`.
23
+ case initializerCantSetNoBackupFlagToGeneralStorageURL = "ZINIT0005"
18
24
  /// Unknown GRPC Service error
19
25
  case serviceUnknownError = "ZSRVC0001"
20
26
  /// LightWalletService.getInfo failed.
@@ -33,6 +39,8 @@ public enum ZcashErrorCode: String {
33
39
  case serviceFetchUTXOsFailed = "ZSRVC0008"
34
40
  /// LightWalletService.blockStream failed.
35
41
  case serviceBlockStreamFailed = "ZSRVC0000"
42
+ /// LightWalletService.getSubtreeRoots failed.
43
+ case serviceSubtreeRootsStreamFailed = "ZSRVC0009"
36
44
  /// SimpleConnectionProvider init of Connection failed.
37
45
  case simpleConnectionProvider = "ZSCPC0001"
38
46
  /// Downloaded file with sapling spending parameters isn't valid.
@@ -51,8 +59,12 @@ public enum ZcashErrorCode: String {
51
59
  case blockDAOLatestBlockHeight = "ZBDAO0003"
52
60
  /// SQLite query failed when fetching the latest block from the database.
53
61
  case blockDAOLatestBlock = "ZBDAO0004"
54
- /// Fetched latesxt block information from DB but can't decode them.
62
+ /// Fetched latest block information from DB but can't decode them.
55
63
  case blockDAOLatestBlockCantDecode = "ZBDAO0005"
64
+ /// SQLite query failed when fetching the first unenhanced block from the database.
65
+ case blockDAOFirstUnenhancedHeight = "ZBDAO0006"
66
+ /// Fetched unenhanced block information from DB but can't decode them.
67
+ case blockDAOFirstUnenhancedCantDecode = "ZBDAO0007"
56
68
  /// Error from rust layer when calling ZcashRustBackend.createAccount
57
69
  case rustCreateAccount = "ZRUST0001"
58
70
  /// Error from rust layer when calling ZcashRustBackend.createToAddress
@@ -113,8 +125,6 @@ public enum ZcashErrorCode: String {
113
125
  case rustPutUnspentTransparentOutput = "ZRUST0029"
114
126
  /// Error unrelated to chain validity from rust layer when calling ZcashRustBackend.validateCombinedChain
115
127
  case rustValidateCombinedChainValidationFailed = "ZRUST0030"
116
- /// Error from rust layer which means that combined chain isn't valid.
117
- case rustValidateCombinedChainInvalidChain = "ZRUST0031"
118
128
  /// Error from rust layer when calling ZcashRustBackend.rewindToHeight
119
129
  case rustRewindToHeight = "ZRUST0032"
120
130
  /// Error from rust layer when calling ZcashRustBackend.rewindCacheToHeight
@@ -143,6 +153,26 @@ public enum ZcashErrorCode: String {
143
153
  case rustGetTransparentReceiverInvalidAddress = "ZRUST0044"
144
154
  /// Transparent receiver generated by rust layer is invalid when calling ZcashRustBackend.getTransparentReceiver
145
155
  case rustGetTransparentReceiverInvalidReceiver = "ZRUST0045"
156
+ /// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putSaplingSubtreeRoots
157
+ case rustPutSaplingSubtreeRootsAllocationProblem = "ZRUST0046"
158
+ /// Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots
159
+ case rustPutSaplingSubtreeRoots = "ZRUST0047"
160
+ /// Error from rust layer when calling ZcashRustBackend.updateChainTip
161
+ case rustUpdateChainTip = "ZRUST0048"
162
+ /// Error from rust layer when calling ZcashRustBackend.suggestScanRanges
163
+ case rustSuggestScanRanges = "ZRUST0049"
164
+ /// Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes.
165
+ case rustGetMemoInvalidTxIdLength = "ZRUST0050"
166
+ /// Error from rust layer when calling ZcashRustBackend.getScanProgress
167
+ case rustGetScanProgress = "ZRUST0051"
168
+ /// Error from rust layer when calling ZcashRustBackend.fullyScannedHeight
169
+ case rustFullyScannedHeight = "ZRUST0052"
170
+ /// Error from rust layer when calling ZcashRustBackend.maxScannedHeight
171
+ case rustMaxScannedHeight = "ZRUST0053"
172
+ /// Error from rust layer when calling ZcashRustBackend.latestCachedBlockHeight
173
+ case rustLatestCachedBlockHeight = "ZRUST0054"
174
+ /// Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%.
175
+ case rustScanProgressOutOfRange = "ZRUST0055"
146
176
  /// SQLite query failed when fetching all accounts from the database.
147
177
  case accountDAOGetAll = "ZADAO0001"
148
178
  /// Fetched accounts from SQLite but can't decode them.
@@ -291,6 +321,14 @@ public enum ZcashErrorCode: String {
291
321
  case compactBlockProcessorChainName = "ZCBPEO0016"
292
322
  /// Consensus BranchIDs don't match this is probably an API or programming error.
293
323
  case compactBlockProcessorConsensusBranchID = "ZCBPEO0017"
324
+ /// Rewind of DownloadBlockAction failed as no action is possible to unwrapp.
325
+ case compactBlockProcessorDownloadBlockActionRewind = "ZCBPEO0018"
326
+ /// Put sapling subtree roots to the DB failed.
327
+ case compactBlockProcessorPutSaplingSubtreeRoots = "ZCBPEO0019"
328
+ /// Getting the `lastScannedHeight` failed but it's supposed to always provide some value.
329
+ case compactBlockProcessorLastScannedHeight = "ZCBPEO0020"
330
+ /// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
331
+ case compactBlockProcessorSupportedSyncAlgorithm = "ZCBPEO0021"
294
332
  /// The synchronizer is unprepared.
295
333
  case synchronizerNotPrepared = "ZSYNCO0001"
296
334
  /// Memos can't be sent to transparent addresses.
@@ -38,6 +38,15 @@ enum ZcashErrorDefinition {
38
38
  /// Alias used to create this instance of the `SDKSynchronizer` is already used by other instance.
39
39
  // sourcery: code="ZINIT0002"
40
40
  case initializerAliasAlreadyInUse(_ alias: ZcashSynchronizerAlias)
41
+ /// Object on disk at `generalStorageURL` path exists. But it file not directory.
42
+ // sourcery: code="ZINIT0003"
43
+ case initializerGeneralStorageExistsButIsFile(_ generalStorageURL: URL)
44
+ /// Can't create directory at `generalStorageURL` path.
45
+ // sourcery: code="ZINIT0004"
46
+ case initializerGeneralStorageCantCreate(_ generalStorageURL: URL, _ error: Error)
47
+ /// Can't set `isExcludedFromBackup` flag to `generalStorageURL`.
48
+ // sourcery: code="ZINIT0005"
49
+ case initializerCantSetNoBackupFlagToGeneralStorageURL(_ generalStorageURL: URL, _ error: Error)
41
50
 
42
51
  // MARK: - LightWalletService
43
52
 
@@ -68,6 +77,9 @@ enum ZcashErrorDefinition {
68
77
  /// LightWalletService.blockStream failed.
69
78
  // sourcery: code="ZSRVC0000"
70
79
  case serviceBlockStreamFailed(_ error: LightWalletServiceError)
80
+ /// LightWalletService.getSubtreeRoots failed.
81
+ // sourcery: code="ZSRVC0009"
82
+ case serviceSubtreeRootsStreamFailed(_ error: LightWalletServiceError)
71
83
 
72
84
  // MARK: SQLite connection
73
85
 
@@ -113,10 +125,18 @@ enum ZcashErrorDefinition {
113
125
  /// - `sqliteError` is error produced by SQLite library.
114
126
  // sourcery: code="ZBDAO0004"
115
127
  case blockDAOLatestBlock(_ sqliteError: Error)
116
- /// Fetched latesxt block information from DB but can't decode them.
128
+ /// Fetched latest block information from DB but can't decode them.
117
129
  /// - `error` is decoding error.
118
130
  // sourcery: code="ZBDAO0005"
119
131
  case blockDAOLatestBlockCantDecode(_ error: Error)
132
+ /// SQLite query failed when fetching the first unenhanced block from the database.
133
+ /// - `sqliteError` is error produced by SQLite library.
134
+ // sourcery: code="ZBDAO0006"
135
+ case blockDAOFirstUnenhancedHeight(_ sqliteError: Error)
136
+ /// Fetched unenhanced block information from DB but can't decode them.
137
+ /// - `error` is decoding error.
138
+ // sourcery: code="ZBDAO0007"
139
+ case blockDAOFirstUnenhancedCantDecode(_ error: Error)
120
140
 
121
141
  // MARK: - Rust
122
142
 
@@ -234,10 +254,6 @@ enum ZcashErrorDefinition {
234
254
  /// - `rustError` contains error generated by the rust layer.
235
255
  // sourcery: code="ZRUST0030"
236
256
  case rustValidateCombinedChainValidationFailed(_ rustError: String)
237
- /// Error from rust layer which means that combined chain isn't valid.
238
- /// - `upperBound` is the height of the highest invalid block (on the assumption that the highest block in the cache database is correct).
239
- // sourcery: code="ZRUST0031"
240
- case rustValidateCombinedChainInvalidChain(_ upperBound: Int32)
241
257
  /// Error from rust layer when calling ZcashRustBackend.rewindToHeight
242
258
  /// - `rustError` contains error generated by the rust layer.
243
259
  // sourcery: code="ZRUST0032"
@@ -290,6 +306,44 @@ enum ZcashErrorDefinition {
290
306
  /// Transparent receiver generated by rust layer is invalid when calling ZcashRustBackend.getTransparentReceiver
291
307
  // sourcery: code="ZRUST0045"
292
308
  case rustGetTransparentReceiverInvalidReceiver
309
+ /// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putSaplingSubtreeRoots
310
+ /// sourcery: code="ZRUST0046"
311
+ case rustPutSaplingSubtreeRootsAllocationProblem
312
+ /// Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots
313
+ /// - `rustError` contains error generated by the rust layer.
314
+ /// sourcery: code="ZRUST0047"
315
+ case rustPutSaplingSubtreeRoots(_ rustError: String)
316
+ /// Error from rust layer when calling ZcashRustBackend.updateChainTip
317
+ /// - `rustError` contains error generated by the rust layer.
318
+ /// sourcery: code="ZRUST0048"
319
+ case rustUpdateChainTip(_ rustError: String)
320
+ /// Error from rust layer when calling ZcashRustBackend.suggestScanRanges
321
+ /// - `rustError` contains error generated by the rust layer.
322
+ /// sourcery: code="ZRUST0049"
323
+ case rustSuggestScanRanges(_ rustError: String)
324
+ /// Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes.
325
+ // sourcery: code="ZRUST0050"
326
+ case rustGetMemoInvalidTxIdLength
327
+ /// Error from rust layer when calling ZcashRustBackend.getScanProgress
328
+ /// - `rustError` contains error generated by the rust layer.
329
+ // sourcery: code="ZRUST0051"
330
+ case rustGetScanProgress(_ rustError: String)
331
+ /// Error from rust layer when calling ZcashRustBackend.fullyScannedHeight
332
+ /// - `rustError` contains error generated by the rust layer.
333
+ // sourcery: code="ZRUST0052"
334
+ case rustFullyScannedHeight(_ rustError: String)
335
+ /// Error from rust layer when calling ZcashRustBackend.maxScannedHeight
336
+ /// - `rustError` contains error generated by the rust layer.
337
+ // sourcery: code="ZRUST0053"
338
+ case rustMaxScannedHeight(_ rustError: String)
339
+ /// Error from rust layer when calling ZcashRustBackend.latestCachedBlockHeight
340
+ /// - `rustError` contains error generated by the rust layer.
341
+ // sourcery: code="ZRUST0054"
342
+ case rustLatestCachedBlockHeight(_ rustError: String)
343
+ /// Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%.
344
+ /// - `progress` value reported
345
+ // sourcery: code="ZRUST0055"
346
+ case rustScanProgressOutOfRange(_ progress: String)
293
347
 
294
348
  // MARK: - Account DAO
295
349
 
@@ -572,7 +626,19 @@ enum ZcashErrorDefinition {
572
626
  /// Consensus BranchIDs don't match this is probably an API or programming error.
573
627
  // sourcery: code="ZCBPEO0017"
574
628
  case compactBlockProcessorConsensusBranchID
575
-
629
+ /// Rewind of DownloadBlockAction failed as no action is possible to unwrapp.
630
+ // sourcery: code="ZCBPEO0018"
631
+ case compactBlockProcessorDownloadBlockActionRewind
632
+ /// Put sapling subtree roots to the DB failed.
633
+ // sourcery: code="ZCBPEO0019"
634
+ case compactBlockProcessorPutSaplingSubtreeRoots(_ error: Error)
635
+ /// Getting the `lastScannedHeight` failed but it's supposed to always provide some value.
636
+ // sourcery: code="ZCBPEO0020"
637
+ case compactBlockProcessorLastScannedHeight
638
+ /// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
639
+ // sourcery: code="ZCBPEO0021"
640
+ case compactBlockProcessorSupportedSyncAlgorithm
641
+
576
642
  // MARK: - SDKSynchronizer
577
643
 
578
644
  /// The synchronizer is unprepared.
@@ -0,0 +1,15 @@
1
+ //
2
+ // Bool+ToData.swift
3
+ //
4
+ //
5
+ // Created by Michal Fousek on 21.05.2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ extension Bool {
11
+ func toData() -> Data {
12
+ var value = self
13
+ return withUnsafeBytes(of: &value) { Data($0) }
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ //
2
+ // Data+ToOtherTypes.swift
3
+ //
4
+ //
5
+ // Created by Michal Fousek on 21.05.2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ extension Data {
11
+ func toInt() -> Int {
12
+ return self.withUnsafeBytes { $0.load(as: Int.self) }
13
+ }
14
+
15
+ func toBool() -> Bool {
16
+ return self.withUnsafeBytes { $0.load(as: Bool.self) }
17
+ }
18
+ }
@@ -0,0 +1,15 @@
1
+ //
2
+ // Int+ToData.swift
3
+ //
4
+ //
5
+ // Created by Michal Fousek on 21.05.2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ extension Int {
11
+ func toData() -> Data {
12
+ var value = self
13
+ return withUnsafeBytes(of: &value) { Data($0) }
14
+ }
15
+ }
@@ -90,6 +90,7 @@ public class Initializer {
90
90
  struct URLs {
91
91
  let fsBlockDbRoot: URL
92
92
  let dataDbURL: URL
93
+ let generalStorageURL: URL
93
94
  let spendParamsURL: URL
94
95
  let outputParamsURL: URL
95
96
  }
@@ -112,6 +113,7 @@ public class Initializer {
112
113
  let alias: ZcashSynchronizerAlias
113
114
  let endpoint: LightWalletEndpoint
114
115
  let fsBlockDbRoot: URL
116
+ let generalStorageURL: URL
115
117
  let dataDbURL: URL
116
118
  let spendParamsURL: URL
117
119
  let outputParamsURL: URL
@@ -142,13 +144,20 @@ public class Initializer {
142
144
  /// - cacheDbURL: previous location of the cacheDb. If you don't know what a cacheDb is and you are adopting this SDK for the first time then
143
145
  /// just pass `nil` here.
144
146
  /// - fsBlockDbRoot: location of the compact blocks cache
147
+ /// - generalStorageURL: Location of the directory where the SDK can store any information it needs. A directory doesn't have to exist. But the
148
+ /// SDK must be able to write to this location after it creates this directory. It is suggested that this directory is
149
+ /// a subdirectory of the `Documents` directory. If this information is stored in `Documents` then the system itself won't
150
+ /// remove these data.
145
151
  /// - dataDbURL: Location of the data db
146
152
  /// - endpoint: the endpoint representing the lightwalletd instance you want to point to
147
153
  /// - spendParamsURL: location of the spend parameters
148
154
  /// - outputParamsURL: location of the output parameters
155
+ /// - loggingPolicy: the `LoggingPolicy` for the logger
156
+ /// - enableBackendTracing: this enables tracing for super detailed debugging. it will slow down everything 10 or 100x.
149
157
  convenience public init(
150
158
  cacheDbURL: URL?,
151
159
  fsBlockDbRoot: URL,
160
+ generalStorageURL: URL,
152
161
  dataDbURL: URL,
153
162
  endpoint: LightWalletEndpoint,
154
163
  network: ZcashNetwork,
@@ -156,7 +165,8 @@ public class Initializer {
156
165
  outputParamsURL: URL,
157
166
  saplingParamsSourceURL: SaplingParamsSourceURL,
158
167
  alias: ZcashSynchronizerAlias = .default,
159
- loggingPolicy: LoggingPolicy = .default(.debug)
168
+ loggingPolicy: LoggingPolicy = .default(.debug),
169
+ enableBackendTracing: Bool = false
160
170
  ) {
161
171
  let container = DIContainer()
162
172
 
@@ -166,6 +176,7 @@ public class Initializer {
166
176
  container: container,
167
177
  cacheDbURL: cacheDbURL,
168
178
  fsBlockDbRoot: fsBlockDbRoot,
179
+ generalStorageURL: generalStorageURL,
169
180
  dataDbURL: dataDbURL,
170
181
  endpoint: endpoint,
171
182
  network: network,
@@ -173,7 +184,8 @@ public class Initializer {
173
184
  outputParamsURL: outputParamsURL,
174
185
  saplingParamsSourceURL: saplingParamsSourceURL,
175
186
  alias: alias,
176
- loggingPolicy: loggingPolicy
187
+ loggingPolicy: loggingPolicy,
188
+ enableBackendTracing: enableBackendTracing
177
189
  )
178
190
 
179
191
  self.init(
@@ -194,6 +206,7 @@ public class Initializer {
194
206
  container: DIContainer,
195
207
  cacheDbURL: URL?,
196
208
  fsBlockDbRoot: URL,
209
+ generalStorageURL: URL,
197
210
  dataDbURL: URL,
198
211
  endpoint: LightWalletEndpoint,
199
212
  network: ZcashNetwork,
@@ -201,7 +214,8 @@ public class Initializer {
201
214
  outputParamsURL: URL,
202
215
  saplingParamsSourceURL: SaplingParamsSourceURL,
203
216
  alias: ZcashSynchronizerAlias = .default,
204
- loggingPolicy: LoggingPolicy = .default(.debug)
217
+ loggingPolicy: LoggingPolicy = .default(.debug),
218
+ enableBackendTracing: Bool = false
205
219
  ) {
206
220
  // It's not possible to fail from constructor. Technically it's possible but it can be pain for the client apps to handle errors thrown
207
221
  // from constructor. So `parsingError` is just stored in initializer and `SDKSynchronizer.prepare()` throw this error if it exists.
@@ -209,6 +223,7 @@ public class Initializer {
209
223
  container: container,
210
224
  cacheDbURL: cacheDbURL,
211
225
  fsBlockDbRoot: fsBlockDbRoot,
226
+ generalStorageURL: generalStorageURL,
212
227
  dataDbURL: dataDbURL,
213
228
  endpoint: endpoint,
214
229
  network: network,
@@ -216,7 +231,8 @@ public class Initializer {
216
231
  outputParamsURL: outputParamsURL,
217
232
  saplingParamsSourceURL: saplingParamsSourceURL,
218
233
  alias: alias,
219
- loggingPolicy: loggingPolicy
234
+ loggingPolicy: loggingPolicy,
235
+ enableBackendTracing: enableBackendTracing
220
236
  )
221
237
 
222
238
  self.init(
@@ -247,6 +263,7 @@ public class Initializer {
247
263
  self.cacheDbURL = cacheDbURL
248
264
  self.rustBackend = container.resolve(ZcashRustBackendWelding.self)
249
265
  self.fsBlockDbRoot = urls.fsBlockDbRoot
266
+ self.generalStorageURL = urls.generalStorageURL
250
267
  self.dataDbURL = urls.dataDbURL
251
268
  self.endpoint = endpoint
252
269
  self.spendParamsURL = urls.spendParamsURL
@@ -278,6 +295,7 @@ public class Initializer {
278
295
  container: DIContainer,
279
296
  cacheDbURL: URL?,
280
297
  fsBlockDbRoot: URL,
298
+ generalStorageURL: URL,
281
299
  dataDbURL: URL,
282
300
  endpoint: LightWalletEndpoint,
283
301
  network: ZcashNetwork,
@@ -285,11 +303,13 @@ public class Initializer {
285
303
  outputParamsURL: URL,
286
304
  saplingParamsSourceURL: SaplingParamsSourceURL,
287
305
  alias: ZcashSynchronizerAlias,
288
- loggingPolicy: LoggingPolicy = .default(.debug)
306
+ loggingPolicy: LoggingPolicy = .default(.debug),
307
+ enableBackendTracing: Bool = false
289
308
  ) -> (URLs, ZcashError?) {
290
309
  let urls = URLs(
291
310
  fsBlockDbRoot: fsBlockDbRoot,
292
311
  dataDbURL: dataDbURL,
312
+ generalStorageURL: generalStorageURL,
293
313
  spendParamsURL: spendParamsURL,
294
314
  outputParamsURL: outputParamsURL
295
315
  )
@@ -304,7 +324,8 @@ public class Initializer {
304
324
  alias: alias,
305
325
  networkType: network.networkType,
306
326
  endpoint: endpoint,
307
- loggingPolicy: loggingPolicy
327
+ loggingPolicy: loggingPolicy,
328
+ enableBackendTracing: enableBackendTracing
308
329
  )
309
330
 
310
331
  return (updatedURLs, parsingError)
@@ -360,10 +381,15 @@ public class Initializer {
360
381
  return .failure(.initializerCantUpdateURLWithAlias(urls.outputParamsURL))
361
382
  }
362
383
 
384
+ guard let updatedGeneralStorageURL = urls.generalStorageURL.updateLastPathComponent(with: alias) else {
385
+ return .failure(.initializerCantUpdateURLWithAlias(urls.generalStorageURL))
386
+ }
387
+
363
388
  return .success(
364
389
  URLs(
365
390
  fsBlockDbRoot: updatedFsBlockDbRoot,
366
391
  dataDbURL: updatedDataDbURL,
392
+ generalStorageURL: updatedGeneralStorageURL,
367
393
  spendParamsURL: updatedSpendParamsURL,
368
394
  outputParamsURL: updateOutputParamsURL
369
395
  )
@@ -383,7 +409,7 @@ public class Initializer {
383
409
  /// - Parameter seed: ZIP-32 Seed bytes for the wallet that will be initialized
384
410
  /// - Throws: `InitializerError.dataDbInitFailed` if the creation of the dataDb fails
385
411
  /// `InitializerError.accountInitFailed` if the account table can't be initialized.
386
- func initialize(with seed: [UInt8]?, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight) async throws -> InitializationResult {
412
+ func initialize(with seed: [UInt8]?, walletBirthday: BlockHeight, for walletMode: WalletInitMode) async throws -> InitializationResult {
387
413
  try await storage.create()
388
414
 
389
415
  if case .seedRequired = try await rustBackend.initDataDb(seed: seed) {
@@ -391,27 +417,22 @@ public class Initializer {
391
417
  }
392
418
 
393
419
  let checkpoint = Checkpoint.birthday(with: walletBirthday, network: network)
394
- do {
395
- try await rustBackend.initBlocksTable(
396
- height: Int32(checkpoint.height),
397
- hash: checkpoint.hash,
398
- time: checkpoint.time,
399
- saplingTree: checkpoint.saplingTree
400
- )
401
- } catch ZcashError.rustInitBlocksTableDataDbNotEmpty {
402
- // this is fine
403
- } catch {
404
- throw error
405
- }
406
420
 
407
421
  self.walletBirthday = checkpoint.height
408
-
409
- do {
410
- try await rustBackend.initAccountsTable(ufvks: viewingKeys)
411
- } catch ZcashError.rustInitAccountsTableDataDbNotEmpty {
412
- // this is fine
413
- } catch {
414
- throw error
422
+
423
+ // If there are no accounts it must be created, the default amount of accounts is 1
424
+ if let seed, try accountRepository.getAll().isEmpty {
425
+ var chainTip: UInt32?
426
+
427
+ if walletMode == .restoreWallet {
428
+ chainTip = UInt32(try await lightWalletService.latestBlockHeight())
429
+ }
430
+
431
+ _ = try await rustBackend.createAccount(
432
+ seed: seed,
433
+ treeState: checkpoint.treeState(),
434
+ recoverUntil: chainTip
435
+ )
415
436
  }
416
437
 
417
438
  return .success
@@ -32,9 +32,6 @@ import Foundation
32
32
  /// We encourage you to check`SDKMetricsTests` and other tests in the Test/PerformanceTests/ folder.
33
33
  public class SDKMetrics {
34
34
  public struct BlockMetricReport: Equatable {
35
- public let startHeight: BlockHeight
36
- public let progressHeight: BlockHeight
37
- public let targetHeight: BlockHeight
38
35
  public let batchSize: Int
39
36
  public let startTime: TimeInterval
40
37
  public let endTime: TimeInterval
@@ -43,7 +40,6 @@ public class SDKMetrics {
43
40
 
44
41
  public enum Operation {
45
42
  case downloadBlocks
46
- case validateBlocks
47
43
  case scanBlocks
48
44
  case enhancement
49
45
  case fetchUTXOs
@@ -75,7 +71,6 @@ public class SDKMetrics {
75
71
  /// `SDKMetrics` focuses deeply on sync process and metrics related to it. By default there are reports around
76
72
  /// block operations like download, validate, etc. This method pushes data on a stack for the specific operation.
77
73
  func pushProgressReport(
78
- progress: BlockProgress,
79
74
  start: Date,
80
75
  end: Date,
81
76
  batchSize: Int,
@@ -84,9 +79,6 @@ public class SDKMetrics {
84
79
  guard isEnabled else { return }
85
80
 
86
81
  let blockMetricReport = BlockMetricReport(
87
- startHeight: progress.startHeight,
88
- progressHeight: progress.progressHeight,
89
- targetHeight: progress.targetHeight,
90
82
  batchSize: batchSize,
91
83
  startTime: start.timeIntervalSinceReferenceDate,
92
84
  endTime: end.timeIntervalSinceReferenceDate
@@ -158,7 +150,6 @@ public class SDKMetrics {
158
150
  extension SDKMetrics {
159
151
  public struct CumulativeSummary: Equatable {
160
152
  public let downloadedBlocksReport: ReportSummary?
161
- public let validatedBlocksReport: ReportSummary?
162
153
  public let scannedBlocksReport: ReportSummary?
163
154
  public let enhancementReport: ReportSummary?
164
155
  public let fetchUTXOsReport: ReportSummary?
@@ -177,7 +168,6 @@ extension SDKMetrics {
177
168
  /// independently. A `ReportSummary` is the result per `operation`, providing min, max and avg times.
178
169
  public func cumulativeSummary() -> CumulativeSummary {
179
170
  let downloadReport = summaryFor(reports: reports[.downloadBlocks])
180
- let validateReport = summaryFor(reports: reports[.validateBlocks])
181
171
  let scanReport = summaryFor(reports: reports[.scanBlocks])
182
172
  let enhancementReport = summaryFor(reports: reports[.enhancement])
183
173
  let fetchUTXOsReport = summaryFor(reports: reports[.fetchUTXOs])
@@ -189,7 +179,6 @@ extension SDKMetrics {
189
179
 
190
180
  return CumulativeSummary(
191
181
  downloadedBlocksReport: downloadReport,
192
- validatedBlocksReport: validateReport,
193
182
  scannedBlocksReport: scanReport,
194
183
  enhancementReport: enhancementReport,
195
184
  fetchUTXOsReport: fetchUTXOsReport,
@@ -217,7 +206,6 @@ extension SDKMetrics {
217
206
  cumulativeSummaries.forEach { summary in
218
207
  finalSummary = CumulativeSummary(
219
208
  downloadedBlocksReport: accumulate(left: finalSummary?.downloadedBlocksReport, right: summary.downloadedBlocksReport),
220
- validatedBlocksReport: accumulate(left: finalSummary?.validatedBlocksReport, right: summary.validatedBlocksReport),
221
209
  scannedBlocksReport: accumulate(left: finalSummary?.scannedBlocksReport, right: summary.scannedBlocksReport),
222
210
  enhancementReport: accumulate(left: finalSummary?.enhancementReport, right: summary.enhancementReport),
223
211
  fetchUTXOsReport: accumulate(left: finalSummary?.fetchUTXOsReport, right: summary.fetchUTXOsReport),
@@ -71,6 +71,18 @@ extension Checkpoint: Decodable {
71
71
  }
72
72
  return height
73
73
  }
74
+
75
+ public func treeState() -> TreeState {
76
+ var ret = TreeState()
77
+ ret.height = UInt64(height)
78
+ ret.hash = hash
79
+ ret.time = time
80
+ ret.saplingTree = saplingTree
81
+ if let tree = orchardTree {
82
+ ret.orchardTree = tree
83
+ }
84
+ return ret
85
+ }
74
86
  }
75
87
 
76
88
  public extension BlockHeight {
@@ -0,0 +1,29 @@
1
+ //
2
+ // ScanProgress.swift
3
+ //
4
+ //
5
+ // Created by Jack Grigg on 06/09/2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ struct ScanProgress: Equatable {
11
+ let numerator: UInt64
12
+ let denominator: UInt64
13
+
14
+ func progress() throws -> Float {
15
+ guard denominator != 0 else {
16
+ // this shouldn't happen but if it does, we need to get notified by clients and work on a fix
17
+ throw ZcashError.rustScanProgressOutOfRange("\(numerator)/\(denominator)")
18
+ }
19
+
20
+ let value = Float(numerator) / Float(denominator)
21
+
22
+ // this shouldn't happen but if it does, we need to get notified by clients and work on a fix
23
+ if value > 1.0 {
24
+ throw ZcashError.rustScanProgressOutOfRange("\(value)")
25
+ }
26
+
27
+ return value
28
+ }
29
+ }
@@ -0,0 +1,31 @@
1
+ //
2
+ // ScanRange.swift
3
+ //
4
+ //
5
+ // Created by Jack Grigg on 17/07/2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ struct ScanRange {
11
+ enum Priority: UInt8 {
12
+ case ignored = 0
13
+ case scanned = 10
14
+ case historic = 20
15
+ case openAdjacent = 30
16
+ case foundNote = 40
17
+ case chainTip = 50
18
+ case verify = 60
19
+
20
+ init(_ value: UInt8) {
21
+ if let priority = Priority(rawValue: value) {
22
+ self = priority
23
+ } else {
24
+ fatalError("The value \(value) is out of the range of priorities.")
25
+ }
26
+ }
27
+ }
28
+
29
+ let range: Range<BlockHeight>
30
+ let priority: Priority
31
+ }
@@ -262,6 +262,21 @@ extension LightWalletGRPCService: LightWalletService {
262
262
  }
263
263
  }
264
264
  }
265
+
266
+ func getSubtreeRoots(_ request: GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error> {
267
+ let stream = compactTxStreamer.getSubtreeRoots(request)
268
+ var iterator = stream.makeAsyncIterator()
269
+
270
+ return AsyncThrowingStream() {
271
+ do {
272
+ guard let subtreeRoot = try await iterator.next() else { return nil }
273
+ return subtreeRoot
274
+ } catch {
275
+ let serviceError = error.mapToServiceError()
276
+ throw ZcashError.serviceSubtreeRootsStreamFailed(serviceError)
277
+ }
278
+ }
279
+ }
265
280
 
266
281
  func closeConnection() {
267
282
  _ = channel.close()