react-native-zcash 0.6.13 → 0.7.0

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 (162) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/android/build.gradle +4 -4
  3. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2470000.json +8 -0
  4. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2480000.json +8 -0
  5. package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +51 -9
  6. package/ios/RNZcash.m +8 -0
  7. package/ios/RNZcash.swift +66 -16
  8. package/ios/ZCashLightClientKit/Block/Actions/DownloadAction.swift +1 -1
  9. package/ios/ZCashLightClientKit/Block/Actions/EnhanceAction.swift +3 -1
  10. package/ios/ZCashLightClientKit/Block/Actions/FetchUTXOsAction.swift +1 -1
  11. package/ios/ZCashLightClientKit/Block/Actions/ProcessSuggestedScanRangesAction.swift +11 -2
  12. package/ios/ZCashLightClientKit/Block/Actions/RewindAction.swift +2 -2
  13. package/ios/ZCashLightClientKit/Block/Actions/ScanAction.swift +28 -11
  14. package/ios/ZCashLightClientKit/Block/Actions/UpdateChainTipAction.swift +4 -4
  15. package/ios/ZCashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +36 -7
  16. package/ios/ZCashLightClientKit/Block/Actions/ValidateServerAction.swift +1 -1
  17. package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +93 -51
  18. package/ios/ZCashLightClientKit/Block/Download/BlockDownloader.swift +0 -26
  19. package/ios/ZCashLightClientKit/Block/Enhance/BlockEnhancer.swift +5 -6
  20. package/ios/ZCashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +1 -11
  21. package/ios/ZCashLightClientKit/Block/SaplingParameters/SaplingParametersHandler.swift +6 -4
  22. package/ios/ZCashLightClientKit/Block/Scan/BlockScanner.swift +10 -12
  23. package/ios/ZCashLightClientKit/Checkpoint/BundleCheckpointSource.swift +38 -0
  24. package/ios/ZCashLightClientKit/Checkpoint/BundleCheckpointURLProvider.swift +40 -0
  25. package/ios/ZCashLightClientKit/{Constants/Checkpoint+Constants.swift → Checkpoint/Checkpoint+helpers.swift} +1 -33
  26. package/ios/ZCashLightClientKit/Checkpoint/CheckpointSource.swift +34 -0
  27. package/ios/ZCashLightClientKit/Checkpoint/CheckpointSourceFactory.swift +14 -0
  28. package/ios/ZCashLightClientKit/ClosureSynchronizer.swift +61 -6
  29. package/ios/ZCashLightClientKit/CombineSynchronizer.swift +63 -4
  30. package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +4 -0
  31. package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +21 -33
  32. package/ios/ZCashLightClientKit/DAO/UnspentTransactionOutputDao.swift +0 -182
  33. package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +0 -173
  34. package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +5 -2
  35. package/ios/ZCashLightClientKit/Error/Sourcery/generateErrorCode.sh +1 -1
  36. package/ios/ZCashLightClientKit/Error/ZcashError.swift +53 -1
  37. package/ios/ZCashLightClientKit/Error/ZcashErrorCode.swift +19 -1
  38. package/ios/ZCashLightClientKit/Error/ZcashErrorCodeDefinition.swift +32 -0
  39. package/ios/ZCashLightClientKit/Initializer.swift +8 -17
  40. package/ios/ZCashLightClientKit/Metrics/SDKMetrics.swift +103 -217
  41. package/ios/ZCashLightClientKit/Model/Proposal.swift +45 -0
  42. package/ios/ZCashLightClientKit/Model/ScanSummary.swift +14 -0
  43. package/ios/ZCashLightClientKit/Model/WalletSummary.swift +58 -0
  44. package/ios/ZCashLightClientKit/Model/WalletTypes.swift +0 -16
  45. package/ios/ZCashLightClientKit/Modules/Service/GRPC/LightWalletGRPCService.swift +5 -3
  46. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proposal.pb.swift +934 -0
  47. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/proposal.proto +138 -0
  48. package/ios/ZCashLightClientKit/Modules/Service/LightWalletService.swift +2 -4
  49. package/ios/ZCashLightClientKit/Providers/LatestBlocksDataProvider.swift +9 -1
  50. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2272500.json +8 -0
  51. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2275000.json +8 -0
  52. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2277500.json +8 -0
  53. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2282500.json +8 -0
  54. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2285000.json +8 -0
  55. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2287500.json +8 -0
  56. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2292500.json +8 -0
  57. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2295000.json +8 -0
  58. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2297500.json +8 -0
  59. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2302500.json +8 -0
  60. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2305000.json +8 -0
  61. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2307500.json +8 -0
  62. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2312500.json +8 -0
  63. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2315000.json +8 -0
  64. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2317500.json +8 -0
  65. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2322500.json +8 -0
  66. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2325000.json +8 -0
  67. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2327500.json +8 -0
  68. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2332500.json +8 -0
  69. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2335000.json +8 -0
  70. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2337500.json +8 -0
  71. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2342500.json +8 -0
  72. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2345000.json +8 -0
  73. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2347500.json +8 -0
  74. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2352500.json +8 -0
  75. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2355000.json +8 -0
  76. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2357500.json +8 -0
  77. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2362500.json +8 -0
  78. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2365000.json +8 -0
  79. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2367500.json +8 -0
  80. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2372500.json +8 -0
  81. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2375000.json +8 -0
  82. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2377500.json +8 -0
  83. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2382500.json +8 -0
  84. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2385000.json +8 -0
  85. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2387500.json +8 -0
  86. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2392500.json +8 -0
  87. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2395000.json +8 -0
  88. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2397500.json +8 -0
  89. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2402500.json +8 -0
  90. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2405000.json +8 -0
  91. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2407500.json +8 -0
  92. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2412500.json +8 -0
  93. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2415000.json +8 -0
  94. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2417500.json +8 -0
  95. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2422500.json +8 -0
  96. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2425000.json +8 -0
  97. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2427500.json +8 -0
  98. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2432500.json +8 -0
  99. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2435000.json +8 -0
  100. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2437500.json +8 -0
  101. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2442500.json +8 -0
  102. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2445000.json +8 -0
  103. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2447500.json +8 -0
  104. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2452500.json +8 -0
  105. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2455000.json +8 -0
  106. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2457500.json +8 -0
  107. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2462500.json +8 -0
  108. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2465000.json +8 -0
  109. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2467500.json +8 -0
  110. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2470000.json +8 -0
  111. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2472500.json +8 -0
  112. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2480000.json +8 -0
  113. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2560000.json +8 -0
  114. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2570000.json +8 -0
  115. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2580000.json +8 -0
  116. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2590000.json +8 -0
  117. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2600000.json +8 -0
  118. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2610000.json +8 -0
  119. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2620000.json +8 -0
  120. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2630000.json +8 -0
  121. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2640000.json +8 -0
  122. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2650000.json +8 -0
  123. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2660000.json +8 -0
  124. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2670000.json +8 -0
  125. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2680000.json +8 -0
  126. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2690000.json +8 -0
  127. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2700000.json +8 -0
  128. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2710000.json +8 -0
  129. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2720000.json +8 -0
  130. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2730000.json +8 -0
  131. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2740000.json +8 -0
  132. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2750000.json +8 -0
  133. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2760000.json +8 -0
  134. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2770000.json +8 -0
  135. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2780000.json +8 -0
  136. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2790000.json +8 -0
  137. package/ios/ZCashLightClientKit/Rust/ZcashKeyDerivationBackend.swift +1 -5
  138. package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +327 -153
  139. package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +78 -36
  140. package/ios/ZCashLightClientKit/Rust/zcashlc.h +1441 -0
  141. package/ios/ZCashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +43 -14
  142. package/ios/ZCashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +52 -14
  143. package/ios/ZCashLightClientKit/Synchronizer/Dependencies.swift +10 -6
  144. package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +220 -70
  145. package/ios/ZCashLightClientKit/Synchronizer.swift +105 -29
  146. package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +61 -32
  147. package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +52 -61
  148. package/ios/ZCashLightClientKit/Utils/DBActor.swift +21 -0
  149. package/ios/ZCashLightClientKit/Utils/LoggingProxy.swift +5 -0
  150. package/ios/ZCashLightClientKit/Utils/OSLogger.swift +71 -14
  151. package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
  152. package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
  153. package/lib/rnzcash.rn.js +21 -6
  154. package/lib/rnzcash.rn.js.map +1 -1
  155. package/lib/src/react-native.d.ts +2 -1
  156. package/lib/src/types.d.ts +9 -1
  157. package/package.json +1 -1
  158. package/src/react-native.ts +23 -4
  159. package/src/types.ts +10 -1
  160. package/ios/ZCashLightClientKit/Model/ScanProgress.swift +0 -29
  161. package/ios/ZCashLightClientKit/Repository/UnspentTransactionOutputRepository.swift +0 -16
  162. /package/ios/ZCashLightClientKit/{Model → Checkpoint}/Checkpoint.swift +0 -0
@@ -70,6 +70,46 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
70
70
  }
71
71
  }
72
72
 
73
+ public func proposeTransfer(
74
+ accountIndex: Int,
75
+ recipient: Recipient,
76
+ amount: Zatoshi,
77
+ memo: Memo?,
78
+ completion: @escaping (Result<Proposal, Error>) -> Void
79
+ ) {
80
+ AsyncToClosureGateway.executeThrowingAction(completion) {
81
+ try await self.synchronizer.proposeTransfer(accountIndex: accountIndex, recipient: recipient, amount: amount, memo: memo)
82
+ }
83
+ }
84
+
85
+ public func proposeShielding(
86
+ accountIndex: Int,
87
+ shieldingThreshold: Zatoshi,
88
+ memo: Memo,
89
+ transparentReceiver: TransparentAddress? = nil,
90
+ completion: @escaping (Result<Proposal?, Error>) -> Void
91
+ ) {
92
+ AsyncToClosureGateway.executeThrowingAction(completion) {
93
+ try await self.synchronizer.proposeShielding(
94
+ accountIndex: accountIndex,
95
+ shieldingThreshold: shieldingThreshold,
96
+ memo: memo,
97
+ transparentReceiver: transparentReceiver
98
+ )
99
+ }
100
+ }
101
+
102
+ public func createProposedTransactions(
103
+ proposal: Proposal,
104
+ spendingKey: UnifiedSpendingKey,
105
+ completion: @escaping (Result<AsyncThrowingStream<TransactionSubmitResult, Error>, Error>) -> Void
106
+ ) {
107
+ AsyncToClosureGateway.executeThrowingAction(completion) {
108
+ try await self.synchronizer.createProposedTransactions(proposal: proposal, spendingKey: spendingKey)
109
+ }
110
+ }
111
+
112
+ @available(*, deprecated, message: "Upcoming SDK 2.1 will create multiple transactions at once for some recipients.")
73
113
  public func sendToAddress(
74
114
  spendingKey: UnifiedSpendingKey,
75
115
  zatoshi: Zatoshi,
@@ -82,6 +122,7 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
82
122
  }
83
123
  }
84
124
 
125
+ @available(*, deprecated, message: "Upcoming SDK 2.1 will create multiple transactions at once for some recipients.")
85
126
  public func shieldFunds(
86
127
  spendingKey: UnifiedSpendingKey,
87
128
  memo: Memo,
@@ -147,21 +188,9 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
147
188
  }
148
189
  }
149
190
 
150
- public func getTransparentBalance(accountIndex: Int, completion: @escaping (Result<WalletBalance, Error>) -> Void) {
151
- AsyncToClosureGateway.executeThrowingAction(completion) {
152
- try await self.synchronizer.getTransparentBalance(accountIndex: accountIndex)
153
- }
154
- }
155
-
156
- public func getShieldedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void) {
157
- AsyncToClosureGateway.executeThrowingAction(completion) {
158
- try await self.synchronizer.getShieldedBalance(accountIndex: accountIndex)
159
- }
160
- }
161
-
162
- public func getShieldedVerifiedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void) {
191
+ public func getAccountBalance(accountIndex: Int, completion: @escaping (Result<AccountBalance?, Error>) -> Void) {
163
192
  AsyncToClosureGateway.executeThrowingAction(completion) {
164
- try await self.synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex)
193
+ try await self.synchronizer.getAccountBalance(accountIndex: accountIndex)
165
194
  }
166
195
  }
167
196
 
@@ -69,6 +69,55 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
69
69
  }
70
70
  }
71
71
 
72
+ public func proposeTransfer(
73
+ accountIndex: Int,
74
+ recipient: Recipient,
75
+ amount: Zatoshi,
76
+ memo: Memo?
77
+ ) -> SinglePublisher<Proposal, Error> {
78
+ AsyncToCombineGateway.executeThrowingAction() {
79
+ try await self.synchronizer.proposeTransfer(accountIndex: accountIndex, recipient: recipient, amount: amount, memo: memo)
80
+ }
81
+ }
82
+
83
+ public func proposefulfillingPaymentURI(
84
+ _ uri: String,
85
+ accountIndex: Int
86
+ ) -> SinglePublisher<Proposal, Error> {
87
+ AsyncToCombineGateway.executeThrowingAction() {
88
+ try await self.synchronizer.proposefulfillingPaymentURI(
89
+ uri,
90
+ accountIndex: accountIndex
91
+ )
92
+ }
93
+ }
94
+
95
+ public func proposeShielding(
96
+ accountIndex: Int,
97
+ shieldingThreshold: Zatoshi,
98
+ memo: Memo,
99
+ transparentReceiver: TransparentAddress? = nil
100
+ ) -> SinglePublisher<Proposal?, Error> {
101
+ AsyncToCombineGateway.executeThrowingAction() {
102
+ try await self.synchronizer.proposeShielding(
103
+ accountIndex: accountIndex,
104
+ shieldingThreshold: shieldingThreshold,
105
+ memo: memo,
106
+ transparentReceiver: transparentReceiver
107
+ )
108
+ }
109
+ }
110
+
111
+ public func createProposedTransactions(
112
+ proposal: Proposal,
113
+ spendingKey: UnifiedSpendingKey
114
+ ) -> SinglePublisher<AsyncThrowingStream<TransactionSubmitResult, Error>, Error> {
115
+ AsyncToCombineGateway.executeThrowingAction() {
116
+ try await self.synchronizer.createProposedTransactions(proposal: proposal, spendingKey: spendingKey)
117
+ }
118
+ }
119
+
120
+ @available(*, deprecated, message: "Upcoming SDK 2.1 will create multiple transactions at once for some recipients.")
72
121
  public func sendToAddress(
73
122
  spendingKey: UnifiedSpendingKey,
74
123
  zatoshi: Zatoshi,
@@ -80,6 +129,7 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
80
129
  }
81
130
  }
82
131
 
132
+ @available(*, deprecated, message: "Upcoming SDK 2.1 will create multiple transactions at once for some recipients.")
83
133
  public func shieldFunds(
84
134
  spendingKey: UnifiedSpendingKey,
85
135
  memo: Memo,
@@ -140,21 +190,9 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
140
190
  }
141
191
  }
142
192
 
143
- public func getTransparentBalance(accountIndex: Int) -> SinglePublisher<WalletBalance, Error> {
144
- AsyncToCombineGateway.executeThrowingAction() {
145
- try await self.synchronizer.getTransparentBalance(accountIndex: accountIndex)
146
- }
147
- }
148
-
149
- public func getShieldedBalance(accountIndex: Int = 0) -> SinglePublisher<Zatoshi, Error> {
150
- AsyncToCombineGateway.executeThrowingAction() {
151
- try await synchronizer.getShieldedBalance(accountIndex: accountIndex)
152
- }
153
- }
154
-
155
- public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> SinglePublisher<Zatoshi, Error> {
193
+ public func getAccountBalance(accountIndex: Int) -> SinglePublisher<AccountBalance?, Error> {
156
194
  AsyncToCombineGateway.executeThrowingAction() {
157
- try await synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex)
195
+ try await self.synchronizer.getAccountBalance(accountIndex: accountIndex)
158
196
  }
159
197
  }
160
198
 
@@ -17,6 +17,10 @@ enum Dependencies {
17
17
  loggingPolicy: Initializer.LoggingPolicy = .default(.debug),
18
18
  enableBackendTracing: Bool = false
19
19
  ) {
20
+ container.register(type: CheckpointSource.self, isSingleton: true) { _ in
21
+ CheckpointSourceFactory.fromBundle(for: networkType)
22
+ }
23
+
20
24
  container.register(type: Logger.self, isSingleton: true) { _ in
21
25
  let logger: Logger
22
26
  switch loggingPolicy {
@@ -32,7 +36,7 @@ enum Dependencies {
32
36
  }
33
37
 
34
38
  container.register(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in
35
- return ZcashRustBackend(
39
+ ZcashRustBackend(
36
40
  dbData: urls.dataDbURL,
37
41
  fsBlockDbRoot: urls.fsBlockDbRoot,
38
42
  spendParamsPath: urls.spendParamsURL,
@@ -43,7 +47,7 @@ enum Dependencies {
43
47
  }
44
48
 
45
49
  container.register(type: LightWalletService.self, isSingleton: true) { _ in
46
- return LightWalletGRPCService(endpoint: endpoint)
50
+ LightWalletGRPCService(endpoint: endpoint)
47
51
  }
48
52
 
49
53
  container.register(type: TransactionRepository.self, isSingleton: true) { _ in
@@ -75,7 +79,7 @@ enum Dependencies {
75
79
  }
76
80
 
77
81
  container.register(type: SDKMetrics.self, isSingleton: true) { _ in
78
- SDKMetrics()
82
+ SDKMetricsImpl()
79
83
  }
80
84
 
81
85
  container.register(type: LatestBlocksDataProvider.self, isSingleton: true) { di in
@@ -96,8 +100,7 @@ enum Dependencies {
96
100
 
97
101
  static func setupCompactBlockProcessor(
98
102
  in container: DIContainer,
99
- config: CompactBlockProcessor.Configuration,
100
- accountRepository: AccountRepository
103
+ config: CompactBlockProcessor.Configuration
101
104
  ) {
102
105
  container.register(type: BlockDownloader.self, isSingleton: true) { di in
103
106
  let service = di.resolve(LightWalletService.self)
@@ -116,6 +119,7 @@ enum Dependencies {
116
119
  }
117
120
 
118
121
  container.register(type: BlockScanner.self, isSingleton: true) { di in
122
+ let service = di.resolve(LightWalletService.self)
119
123
  let rustBackend = di.resolve(ZcashRustBackendWelding.self)
120
124
  let transactionRepository = di.resolve(TransactionRepository.self)
121
125
  let metrics = di.resolve(SDKMetrics.self)
@@ -129,6 +133,7 @@ enum Dependencies {
129
133
  return BlockScannerImpl(
130
134
  config: blockScannerConfig,
131
135
  rustBackend: rustBackend,
136
+ service: service,
132
137
  transactionRepository: transactionRepository,
133
138
  metrics: metrics,
134
139
  logger: logger
@@ -159,7 +164,6 @@ enum Dependencies {
159
164
  let logger = di.resolve(Logger.self)
160
165
 
161
166
  return UTXOFetcherImpl(
162
- accountRepository: accountRepository,
163
167
  blockDownloaderService: blockDownloaderService,
164
168
  config: utxoFetcherConfig,
165
169
  rustBackend: rustBackend,
@@ -12,6 +12,7 @@ import Combine
12
12
  /// Synchronizer implementation for UIKit and iOS 13+
13
13
  // swiftlint:disable type_body_length
14
14
  public class SDKSynchronizer: Synchronizer {
15
+
15
16
  public var alias: ZcashSynchronizerAlias { initializer.alias }
16
17
 
17
18
  private lazy var streamsUpdateQueue = { DispatchQueue(label: "streamsUpdateQueue_\(initializer.alias.description)") }()
@@ -22,7 +23,7 @@ public class SDKSynchronizer: Synchronizer {
22
23
  private let eventSubject = PassthroughSubject<SynchronizerEvent, Never>()
23
24
  public var eventStream: AnyPublisher<SynchronizerEvent, Never> { eventSubject.eraseToAnyPublisher() }
24
25
 
25
- public let metrics: SDKMetrics
26
+ let metrics: SDKMetrics
26
27
  public let logger: Logger
27
28
 
28
29
  // Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead.
@@ -39,13 +40,11 @@ public class SDKSynchronizer: Synchronizer {
39
40
  public let network: ZcashNetwork
40
41
  private let transactionEncoder: TransactionEncoder
41
42
  private let transactionRepository: TransactionRepository
42
- private let utxoRepository: UnspentTransactionOutputRepository
43
43
 
44
44
  private let syncSessionIDGenerator: SyncSessionIDGenerator
45
45
  private let syncSession: SyncSession
46
46
  private let syncSessionTicker: SessionTicker
47
- private var syncStartDate: Date?
48
- let latestBlocksDataProvider: LatestBlocksDataProvider
47
+ var latestBlocksDataProvider: LatestBlocksDataProvider
49
48
 
50
49
  /// Creates an SDKSynchronizer instance
51
50
  /// - Parameter initializer: a wallet Initializer object
@@ -55,7 +54,6 @@ public class SDKSynchronizer: Synchronizer {
55
54
  initializer: initializer,
56
55
  transactionEncoder: WalletTransactionEncoder(initializer: initializer),
57
56
  transactionRepository: initializer.transactionRepository,
58
- utxoRepository: UTXORepositoryBuilder.build(initializer: initializer),
59
57
  blockProcessor: CompactBlockProcessor(
60
58
  initializer: initializer,
61
59
  walletBirthdayProvider: { initializer.walletBirthday }
@@ -69,7 +67,6 @@ public class SDKSynchronizer: Synchronizer {
69
67
  initializer: Initializer,
70
68
  transactionEncoder: TransactionEncoder,
71
69
  transactionRepository: TransactionRepository,
72
- utxoRepository: UnspentTransactionOutputRepository,
73
70
  blockProcessor: CompactBlockProcessor,
74
71
  syncSessionTicker: SessionTicker
75
72
  ) {
@@ -78,7 +75,6 @@ public class SDKSynchronizer: Synchronizer {
78
75
  self.initializer = initializer
79
76
  self.transactionEncoder = transactionEncoder
80
77
  self.transactionRepository = transactionRepository
81
- self.utxoRepository = utxoRepository
82
78
  self.blockProcessor = blockProcessor
83
79
  self.network = initializer.network
84
80
  self.metrics = initializer.container.resolve(SDKMetrics.self)
@@ -104,6 +100,7 @@ public class SDKSynchronizer: Synchronizer {
104
100
 
105
101
  func updateStatus(_ newValue: InternalSyncStatus, updateExternalStatus: Bool = true) async {
106
102
  let oldValue = await underlyingStatus.update(newValue)
103
+ logger.info("Synchronizer's status updated from \(oldValue) to \(newValue)")
107
104
  await notify(oldStatus: oldValue, newStatus: newValue, updateExternalStatus: updateExternalStatus)
108
105
  }
109
106
 
@@ -136,8 +133,6 @@ public class SDKSynchronizer: Synchronizer {
136
133
  throw error
137
134
  }
138
135
 
139
- try await utxoRepository.initialise()
140
-
141
136
  if case .seedRequired = try await self.initializer.initialize(with: seed, walletBirthday: walletBirthday, for: walletMode) {
142
137
  return .seedRequired
143
138
  }
@@ -164,8 +159,8 @@ public class SDKSynchronizer: Synchronizer {
164
159
  await blockProcessor.start(retry: retry)
165
160
 
166
161
  case .stopped, .synced, .disconnected, .error:
167
- await updateStatus(.syncing(0))
168
- syncStartDate = Date()
162
+ let syncProgress = (try? await initializer.rustBackend.getWalletSummary()?.scanProgress?.progress()) ?? 0
163
+ await updateStatus(.syncing(syncProgress))
169
164
  await blockProcessor.start(retry: retry)
170
165
  }
171
166
  }
@@ -244,13 +239,6 @@ public class SDKSynchronizer: Synchronizer {
244
239
  await latestBlocksDataProvider.updateScannedData()
245
240
 
246
241
  await updateStatus(.synced)
247
-
248
- if let syncStartDate {
249
- metrics.pushSyncReport(
250
- start: syncStartDate,
251
- end: Date()
252
- )
253
- }
254
242
  }
255
243
 
256
244
  private func foundTransactions(transactions: [ZcashTransaction.Overview], in range: CompactBlockRange) {
@@ -272,6 +260,99 @@ public class SDKSynchronizer: Synchronizer {
272
260
 
273
261
  // MARK: Synchronizer methods
274
262
 
263
+ public func proposeTransfer(accountIndex: Int, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal {
264
+ try throwIfUnprepared()
265
+
266
+ if case Recipient.transparent = recipient, memo != nil {
267
+ throw ZcashError.synchronizerSendMemoToTransparentAddress
268
+ }
269
+
270
+ let proposal = try await transactionEncoder.proposeTransfer(
271
+ accountIndex: accountIndex,
272
+ recipient: recipient.stringEncoded,
273
+ amount: amount,
274
+ memoBytes: memo?.asMemoBytes()
275
+ )
276
+
277
+ return proposal
278
+ }
279
+
280
+ public func proposeShielding(
281
+ accountIndex: Int,
282
+ shieldingThreshold: Zatoshi,
283
+ memo: Memo,
284
+ transparentReceiver: TransparentAddress? = nil
285
+ ) async throws -> Proposal? {
286
+ try throwIfUnprepared()
287
+
288
+ return try await transactionEncoder.proposeShielding(
289
+ accountIndex: accountIndex,
290
+ shieldingThreshold: shieldingThreshold,
291
+ memoBytes: memo.asMemoBytes(),
292
+ transparentReceiver: transparentReceiver?.stringEncoded
293
+ )
294
+ }
295
+
296
+ public func proposefulfillingPaymentURI(
297
+ _ uri: String,
298
+ accountIndex: Int
299
+ ) async throws -> Proposal {
300
+ do {
301
+ try throwIfUnprepared()
302
+ return try await transactionEncoder.proposeFulfillingPaymentFromURI(
303
+ uri,
304
+ accountIndex: accountIndex
305
+ )
306
+ } catch ZcashError.rustCreateToAddress(let error) {
307
+ throw ZcashError.rustProposeTransferFromURI(error)
308
+ } catch {
309
+ throw error
310
+ }
311
+ }
312
+
313
+ public func createProposedTransactions(
314
+ proposal: Proposal,
315
+ spendingKey: UnifiedSpendingKey
316
+ ) async throws -> AsyncThrowingStream<TransactionSubmitResult, Error> {
317
+ try throwIfUnprepared()
318
+
319
+ try await SaplingParameterDownloader.downloadParamsIfnotPresent(
320
+ spendURL: initializer.spendParamsURL,
321
+ spendSourceURL: initializer.saplingParamsSourceURL.spendParamFileURL,
322
+ outputURL: initializer.outputParamsURL,
323
+ outputSourceURL: initializer.saplingParamsSourceURL.outputParamFileURL,
324
+ logger: logger
325
+ )
326
+
327
+ let transactions = try await transactionEncoder.createProposedTransactions(
328
+ proposal: proposal,
329
+ spendingKey: spendingKey
330
+ )
331
+ var iterator = transactions.makeIterator()
332
+ var submitFailed = false
333
+
334
+ return AsyncThrowingStream() {
335
+ guard let transaction = iterator.next() else { return nil }
336
+
337
+ if submitFailed {
338
+ return .notAttempted(txId: transaction.rawID)
339
+ } else {
340
+ let encodedTransaction = try transaction.encodedTransaction()
341
+
342
+ do {
343
+ try await self.transactionEncoder.submit(transaction: encodedTransaction)
344
+ return TransactionSubmitResult.success(txId: transaction.rawID)
345
+ } catch ZcashError.serviceSubmitFailed(let error) {
346
+ submitFailed = true
347
+ return TransactionSubmitResult.grpcFailure(txId: transaction.rawID, error: error)
348
+ } catch TransactionEncoderError.submitError(let code, let message) {
349
+ submitFailed = true
350
+ return TransactionSubmitResult.submitFailure(txId: transaction.rawID, code: code, description: message)
351
+ }
352
+ }
353
+ }
354
+ }
355
+
275
356
  public func sendToAddress(
276
357
  spendingKey: UnifiedSpendingKey,
277
358
  zatoshi: Zatoshi,
@@ -309,20 +390,31 @@ public class SDKSynchronizer: Synchronizer {
309
390
 
310
391
  // let's see if there are funds to shield
311
392
  let accountIndex = Int(spendingKey.account)
312
- let tBalance = try await self.getTransparentBalance(accountIndex: accountIndex)
393
+
394
+ guard let tBalance = try await self.getAccountBalance(accountIndex: accountIndex)?.unshielded else {
395
+ throw ZcashError.synchronizerSpendingKeyDoesNotBelongToTheWallet
396
+ }
313
397
 
314
398
  // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet.
315
- guard tBalance.verified >= self.network.constants.defaultFee() else {
399
+ guard tBalance >= self.network.constants.defaultFee() else {
316
400
  throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds
317
401
  }
318
402
 
319
- let transaction = try await transactionEncoder.createShieldingTransaction(
320
- spendingKey: spendingKey,
403
+ guard let proposal = try await transactionEncoder.proposeShielding(
404
+ accountIndex: Int(spendingKey.account),
321
405
  shieldingThreshold: shieldingThreshold,
322
406
  memoBytes: memo.asMemoBytes(),
323
- from: Int(spendingKey.account)
407
+ transparentReceiver: nil
408
+ ) else { throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds }
409
+
410
+ let transactions = try await transactionEncoder.createProposedTransactions(
411
+ proposal: proposal,
412
+ spendingKey: spendingKey
324
413
  )
325
414
 
415
+ assert(transactions.count == 1, "Rust backend doesn't produce multiple transactions yet")
416
+ let transaction = transactions[0]
417
+
326
418
  let encodedTx = try transaction.encodedTransaction()
327
419
 
328
420
  try await transactionEncoder.submit(transaction: encodedTx)
@@ -343,14 +435,21 @@ public class SDKSynchronizer: Synchronizer {
343
435
  throw ZcashError.synchronizerSendMemoToTransparentAddress
344
436
  }
345
437
 
346
- let transaction = try await transactionEncoder.createTransaction(
347
- spendingKey: spendingKey,
348
- zatoshi: zatoshi,
349
- to: recipient.stringEncoded,
350
- memoBytes: memo?.asMemoBytes(),
351
- from: Int(spendingKey.account)
438
+ let proposal = try await transactionEncoder.proposeTransfer(
439
+ accountIndex: Int(spendingKey.account),
440
+ recipient: recipient.stringEncoded,
441
+ amount: zatoshi,
442
+ memoBytes: memo?.asMemoBytes()
352
443
  )
353
444
 
445
+ let transactions = try await transactionEncoder.createProposedTransactions(
446
+ proposal: proposal,
447
+ spendingKey: spendingKey
448
+ )
449
+
450
+ assert(transactions.count == 1, "Rust backend doesn't produce multiple transactions yet")
451
+ let transaction = transactions[0]
452
+
354
453
  let encodedTransaction = try transaction.encodedTransaction()
355
454
 
356
455
  try await transactionEncoder.submit(transaction: encodedTransaction)
@@ -397,40 +496,13 @@ public class SDKSynchronizer: Synchronizer {
397
496
  try await blockProcessor.latestHeight()
398
497
  }
399
498
 
400
- public func latestUTXOs(address: String) async throws -> [UnspentTransactionOutputEntity] {
401
- try throwIfUnprepared()
402
-
403
- guard initializer.isValidTransparentAddress(address) else {
404
- throw ZcashError.synchronizerLatestUTXOsInvalidTAddress
405
- }
406
-
407
- let stream = initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.saplingActivationHeight)
408
-
409
- // swiftlint:disable:next array_constructor
410
- var utxos: [UnspentTransactionOutputEntity] = []
411
- for try await transactionEntity in stream {
412
- utxos.append(transactionEntity)
413
- }
414
- try await self.utxoRepository.clearAll(address: address)
415
- try await self.utxoRepository.store(utxos: utxos)
416
- return utxos
417
- }
418
-
419
499
  public func refreshUTXOs(address: TransparentAddress, from height: BlockHeight) async throws -> RefreshedUTXOs {
420
500
  try throwIfUnprepared()
421
501
  return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height)
422
502
  }
423
503
 
424
- public func getShieldedBalance(accountIndex: Int = 0) async throws -> Zatoshi {
425
- let balance = try await initializer.rustBackend.getBalance(account: Int32(accountIndex))
426
-
427
- return Zatoshi(balance)
428
- }
429
-
430
- public func getShieldedVerifiedBalance(accountIndex: Int = 0) async throws -> Zatoshi {
431
- let balance = try await initializer.rustBackend.getVerifiedBalance(account: Int32(accountIndex))
432
-
433
- return Zatoshi(balance)
504
+ public func getAccountBalance(accountIndex: Int = 0) async throws -> AccountBalance? {
505
+ try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]
434
506
  }
435
507
 
436
508
  public func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
@@ -445,11 +517,6 @@ public class SDKSynchronizer: Synchronizer {
445
517
  try await blockProcessor.getTransparentAddress(accountIndex: accountIndex)
446
518
  }
447
519
 
448
- /// Returns the last stored transparent balance
449
- public func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance {
450
- try await blockProcessor.getTransparentBalance(accountIndex: accountIndex)
451
- }
452
-
453
520
  // MARK: Rewind
454
521
 
455
522
  public func rewind(_ policy: RewindPolicy) -> AnyPublisher<Void, Error> {
@@ -536,17 +603,100 @@ public class SDKSynchronizer: Synchronizer {
536
603
 
537
604
  return subject.eraseToAnyPublisher()
538
605
  }
539
-
606
+
607
+ public func isSeedRelevantToAnyDerivedAccount(seed: [UInt8]) async throws -> Bool {
608
+ try await initializer.rustBackend.isSeedRelevantToAnyDerivedAccount(seed: seed)
609
+ }
610
+
611
+ // MARK: Server switch
612
+
613
+ public func switchTo(endpoint: LightWalletEndpoint) async throws {
614
+ // Stop synchronization
615
+ let status = await self.status
616
+ if status != .stopped && status != .disconnected {
617
+ await blockProcessor.stop()
618
+ }
619
+
620
+ // Validation of the server is first because any custom endpoint can be passed here
621
+ // Extra instance of the service is created with lower timeout ofr a single call
622
+ initializer.container.register(type: LightWalletService.self, isSingleton: true) { _ in
623
+ LightWalletGRPCService(
624
+ host: endpoint.host,
625
+ port: endpoint.port,
626
+ secure: endpoint.secure,
627
+ singleCallTimeout: 5000,
628
+ streamingCallTimeout: endpoint.streamingCallTimeoutInMillis
629
+ )
630
+ }
631
+
632
+ let validateSever = ValidateServerAction(
633
+ container: initializer.container,
634
+ configProvider: CompactBlockProcessor.ConfigProvider(config: await blockProcessor.config)
635
+ )
636
+
637
+ do {
638
+ _ = try await validateSever.run(with: ActionContextImpl(state: .idle)) { _ in }
639
+ } catch {
640
+ throw ZcashError.synchronizerServerSwitch
641
+ }
642
+
643
+ // The `ValidateServerAction` confirmed the server is ok and we can continue
644
+ // final instance of the service will be instantiated and propagated to the all parties
645
+
646
+ // SWITCH TO NEW ENDPOINT
647
+
648
+ // LightWalletService dependency update
649
+ initializer.container.register(type: LightWalletService.self, isSingleton: true) { _ in
650
+ LightWalletGRPCService(endpoint: endpoint)
651
+ }
652
+
653
+ // DEPENDENCIES
654
+
655
+ // BlockDownloaderService dependency update
656
+ initializer.container.register(type: BlockDownloaderService.self, isSingleton: true) { di in
657
+ let service = di.resolve(LightWalletService.self)
658
+ let storage = di.resolve(CompactBlockRepository.self)
659
+
660
+ return BlockDownloaderServiceImpl(service: service, storage: storage)
661
+ }
662
+
663
+ // LatestBlocksDataProvider dependency update
664
+ initializer.container.register(type: LatestBlocksDataProvider.self, isSingleton: true) { di in
665
+ let service = di.resolve(LightWalletService.self)
666
+ let rustBackend = di.resolve(ZcashRustBackendWelding.self)
667
+
668
+ return LatestBlocksDataProviderImpl(service: service, rustBackend: rustBackend)
669
+ }
670
+
671
+ // CompactBlockProcessor dependency update
672
+ Dependencies.setupCompactBlockProcessor(
673
+ in: initializer.container,
674
+ config: await blockProcessor.config
675
+ )
676
+
677
+ // INITIALIZER
678
+ initializer.lightWalletService = initializer.container.resolve(LightWalletService.self)
679
+ initializer.blockDownloaderService = initializer.container.resolve(BlockDownloaderService.self)
680
+ initializer.endpoint = endpoint
681
+
682
+ // SELF
683
+ self.latestBlocksDataProvider = initializer.container.resolve(LatestBlocksDataProvider.self)
684
+
685
+ // COMPACT BLOCK PROCESSOR
686
+ await blockProcessor.updateService(initializer.container)
687
+
688
+ // Start synchronization
689
+ if status != .unprepared {
690
+ try await start(retry: true)
691
+ }
692
+ }
693
+
540
694
  // MARK: notify state
541
695
 
542
696
  private func snapshotState(status: InternalSyncStatus) async -> SynchronizerState {
543
- return await SynchronizerState(
697
+ await SynchronizerState(
544
698
  syncSessionID: syncSession.value,
545
- shieldedBalance: WalletBalance(
546
- verified: (try? await getShieldedVerifiedBalance()) ?? .zero,
547
- total: (try? await getShieldedBalance()) ?? .zero
548
- ),
549
- transparentBalance: (try? await blockProcessor.getTransparentBalance(accountIndex: 0)) ?? .zero,
699
+ accountBalance: try? await getAccountBalance(),
550
700
  internalSyncStatus: status,
551
701
  latestBlockHeight: latestBlocksDataProvider.latestBlockHeight
552
702
  )