react-native-zcash 0.9.13 → 0.10.1-beta.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 (277) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/android/build.gradle +6 -6
  3. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/3130000.json +8 -0
  4. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/3140000.json +8 -0
  5. package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +126 -69
  6. package/ios/RNZcash.m +0 -5
  7. package/ios/RNZcash.swift +153 -104
  8. package/ios/ZCashLightClientKit/Account/Account.swift +48 -0
  9. package/ios/ZCashLightClientKit/Account/AccountMetadataKey.swift +96 -0
  10. package/ios/ZCashLightClientKit/Block/Actions/ScanAction.swift +23 -4
  11. package/ios/ZCashLightClientKit/Block/Actions/UpdateChainTipAction.swift +6 -2
  12. package/ios/ZCashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +4 -2
  13. package/ios/ZCashLightClientKit/Block/Actions/ValidateServerAction.swift +4 -1
  14. package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +83 -16
  15. package/ios/ZCashLightClientKit/Block/Download/BlockDownloader.swift +4 -2
  16. package/ios/ZCashLightClientKit/Block/Download/BlockDownloaderService.swift +22 -19
  17. package/ios/ZCashLightClientKit/Block/Enhance/BlockEnhancer.swift +50 -19
  18. package/ios/ZCashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +5 -3
  19. package/ios/ZCashLightClientKit/Block/SaplingParameters/SaplingParametersHandler.swift +22 -5
  20. package/ios/ZCashLightClientKit/Block/Scan/BlockScanner.swift +2 -1
  21. package/ios/ZCashLightClientKit/Block/Utils/CompactBlockProgress.swift +5 -3
  22. package/ios/ZCashLightClientKit/Checkpoint/BundleCheckpointSource.swift +88 -0
  23. package/ios/ZCashLightClientKit/Checkpoint/CheckpointSource.swift +4 -0
  24. package/ios/ZCashLightClientKit/ClosureSynchronizer.swift +52 -21
  25. package/ios/ZCashLightClientKit/CombineSynchronizer.swift +49 -27
  26. package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +8 -2
  27. package/ios/ZCashLightClientKit/DAO/BlockDao.swift +65 -0
  28. package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +86 -1
  29. package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +4 -4
  30. package/ios/ZCashLightClientKit/Entity/Pczt.swift +10 -0
  31. package/ios/ZCashLightClientKit/Entity/SentNoteEntity.swift +2 -2
  32. package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +40 -16
  33. package/ios/ZCashLightClientKit/Error/Sourcery/generateErrorCode.sh +1 -1
  34. package/ios/ZCashLightClientKit/Error/ZcashError.swift +182 -14
  35. package/ios/ZCashLightClientKit/Error/ZcashErrorCode.swift +63 -5
  36. package/ios/ZCashLightClientKit/Error/ZcashErrorCodeDefinition.swift +122 -12
  37. package/ios/ZCashLightClientKit/Initializer.swift +49 -14
  38. package/ios/ZCashLightClientKit/Metrics/SDKMetrics.swift +15 -6
  39. package/ios/ZCashLightClientKit/Model/SingleUseTransparentAddress.swift +29 -0
  40. package/ios/ZCashLightClientKit/Model/TransactionDataRequest.swift +83 -2
  41. package/ios/ZCashLightClientKit/Model/WalletSummary.swift +21 -4
  42. package/ios/ZCashLightClientKit/Model/WalletTypes.swift +38 -8
  43. package/ios/ZCashLightClientKit/Modules/Service/GRPC/LightWalletGRPCService.swift +177 -45
  44. package/ios/ZCashLightClientKit/Modules/Service/LightWalletService.swift +63 -16
  45. package/ios/ZCashLightClientKit/Modules/Service/Tor/LightWalletGRPCServiceOverTor.swift +273 -0
  46. package/ios/ZCashLightClientKit/Providers/LatestBlocksDataProvider.swift +5 -2
  47. package/ios/ZCashLightClientKit/Repository/TransactionRepository.swift +2 -0
  48. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2675000.json +8 -0
  49. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2677500.json +8 -0
  50. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2682500.json +8 -0
  51. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2685000.json +8 -0
  52. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2687500.json +8 -0
  53. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2692500.json +8 -0
  54. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2695000.json +8 -0
  55. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2697500.json +8 -0
  56. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2702500.json +8 -0
  57. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2705000.json +8 -0
  58. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2707500.json +8 -0
  59. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2712500.json +8 -0
  60. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2715000.json +8 -0
  61. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2717500.json +8 -0
  62. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2722500.json +8 -0
  63. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2725000.json +8 -0
  64. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2727500.json +8 -0
  65. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2732500.json +8 -0
  66. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2735000.json +8 -0
  67. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2737500.json +8 -0
  68. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2742500.json +8 -0
  69. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2745000.json +8 -0
  70. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2747500.json +8 -0
  71. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2752500.json +8 -0
  72. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2755000.json +8 -0
  73. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2757500.json +8 -0
  74. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2762500.json +8 -0
  75. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2765000.json +8 -0
  76. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2767500.json +8 -0
  77. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2772500.json +8 -0
  78. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2775000.json +8 -0
  79. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2777500.json +8 -0
  80. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2782500.json +8 -0
  81. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2785000.json +8 -0
  82. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2787500.json +8 -0
  83. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2792500.json +8 -0
  84. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2795000.json +8 -0
  85. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2797500.json +8 -0
  86. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2802500.json +8 -0
  87. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2805000.json +8 -0
  88. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2807500.json +8 -0
  89. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2812500.json +8 -0
  90. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2815000.json +8 -0
  91. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2817500.json +8 -0
  92. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2822500.json +8 -0
  93. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2825000.json +8 -0
  94. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2827500.json +8 -0
  95. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2832500.json +8 -0
  96. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2835000.json +8 -0
  97. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2837500.json +8 -0
  98. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2842500.json +8 -0
  99. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2845000.json +8 -0
  100. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2847500.json +8 -0
  101. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2852500.json +8 -0
  102. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2855000.json +8 -0
  103. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2857500.json +8 -0
  104. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2862500.json +8 -0
  105. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2865000.json +8 -0
  106. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2867500.json +8 -0
  107. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2872500.json +8 -0
  108. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2875000.json +8 -0
  109. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2877500.json +8 -0
  110. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2882500.json +8 -0
  111. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2885000.json +8 -0
  112. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2887500.json +8 -0
  113. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2892500.json +8 -0
  114. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2895000.json +8 -0
  115. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2897500.json +8 -0
  116. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2902500.json +8 -0
  117. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2905000.json +8 -0
  118. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2907500.json +8 -0
  119. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2912500.json +8 -0
  120. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2915000.json +8 -0
  121. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2917500.json +8 -0
  122. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2922500.json +8 -0
  123. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2925000.json +8 -0
  124. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2927500.json +8 -0
  125. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2932500.json +8 -0
  126. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2935000.json +8 -0
  127. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2937500.json +8 -0
  128. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2942500.json +8 -0
  129. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2945000.json +8 -0
  130. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2947500.json +8 -0
  131. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2952500.json +8 -0
  132. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2955000.json +8 -0
  133. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2957500.json +8 -0
  134. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2962500.json +8 -0
  135. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2965000.json +8 -0
  136. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2967500.json +8 -0
  137. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2972500.json +8 -0
  138. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2975000.json +8 -0
  139. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2977500.json +8 -0
  140. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2982500.json +8 -0
  141. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2985000.json +8 -0
  142. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2987500.json +8 -0
  143. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2992500.json +8 -0
  144. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2995000.json +8 -0
  145. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2997500.json +8 -0
  146. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3002500.json +8 -0
  147. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3005000.json +8 -0
  148. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3007500.json +8 -0
  149. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3012500.json +8 -0
  150. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3015000.json +8 -0
  151. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3017500.json +8 -0
  152. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3022500.json +8 -0
  153. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3025000.json +8 -0
  154. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3027500.json +8 -0
  155. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3032500.json +8 -0
  156. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3035000.json +8 -0
  157. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3037500.json +8 -0
  158. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3042500.json +8 -0
  159. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3045000.json +8 -0
  160. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3047500.json +8 -0
  161. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3052500.json +8 -0
  162. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3055000.json +8 -0
  163. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3057500.json +8 -0
  164. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3062500.json +8 -0
  165. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3065000.json +8 -0
  166. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3067500.json +8 -0
  167. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3072500.json +8 -0
  168. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3075000.json +8 -0
  169. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3077500.json +8 -0
  170. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3082500.json +8 -0
  171. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3085000.json +8 -0
  172. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3087500.json +8 -0
  173. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3092500.json +8 -0
  174. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3095000.json +8 -0
  175. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3097500.json +8 -0
  176. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3102500.json +8 -0
  177. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3105000.json +8 -0
  178. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3107500.json +8 -0
  179. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3112500.json +8 -0
  180. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3115000.json +8 -0
  181. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3117500.json +8 -0
  182. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3122500.json +8 -0
  183. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3125000.json +8 -0
  184. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3127500.json +8 -0
  185. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3130000.json +8 -0
  186. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/3140000.json +8 -0
  187. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3010000.json +8 -0
  188. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3020000.json +8 -0
  189. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3030000.json +8 -0
  190. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3040000.json +8 -0
  191. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3050000.json +8 -0
  192. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3060000.json +8 -0
  193. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3070000.json +8 -0
  194. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3080000.json +8 -0
  195. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3090000.json +8 -0
  196. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3100000.json +8 -0
  197. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3110000.json +8 -0
  198. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3120000.json +8 -0
  199. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3130000.json +8 -0
  200. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3140000.json +8 -0
  201. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3150000.json +8 -0
  202. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3160000.json +8 -0
  203. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3170000.json +8 -0
  204. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3180000.json +8 -0
  205. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3190000.json +8 -0
  206. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3200000.json +8 -0
  207. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3210000.json +8 -0
  208. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3220000.json +8 -0
  209. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3230000.json +8 -0
  210. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3240000.json +8 -0
  211. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3250000.json +8 -0
  212. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3260000.json +8 -0
  213. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3270000.json +8 -0
  214. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3280000.json +8 -0
  215. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3290000.json +8 -0
  216. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3300000.json +8 -0
  217. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3310000.json +8 -0
  218. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3320000.json +8 -0
  219. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3330000.json +8 -0
  220. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3340000.json +8 -0
  221. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3350000.json +8 -0
  222. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3360000.json +8 -0
  223. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3370000.json +8 -0
  224. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3380000.json +8 -0
  225. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3390000.json +8 -0
  226. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3400000.json +8 -0
  227. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3410000.json +8 -0
  228. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3420000.json +8 -0
  229. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3430000.json +8 -0
  230. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3440000.json +8 -0
  231. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3450000.json +8 -0
  232. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3460000.json +8 -0
  233. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3470000.json +8 -0
  234. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3480000.json +8 -0
  235. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3490000.json +8 -0
  236. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3500000.json +8 -0
  237. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3510000.json +8 -0
  238. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3520000.json +8 -0
  239. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3530000.json +8 -0
  240. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3540000.json +8 -0
  241. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3550000.json +8 -0
  242. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3560000.json +8 -0
  243. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3570000.json +8 -0
  244. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3580000.json +8 -0
  245. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3590000.json +8 -0
  246. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3600000.json +8 -0
  247. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3610000.json +8 -0
  248. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3620000.json +8 -0
  249. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3630000.json +8 -0
  250. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3640000.json +8 -0
  251. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3650000.json +8 -0
  252. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3660000.json +8 -0
  253. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/3670000.json +8 -0
  254. package/ios/ZCashLightClientKit/Rust/ZcashKeyDerivationBackend.swift +89 -10
  255. package/ios/ZCashLightClientKit/Rust/ZcashKeyDerivationBackendWelding.swift +39 -3
  256. package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +532 -74
  257. package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +97 -14
  258. package/ios/ZCashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +104 -28
  259. package/ios/ZCashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +105 -31
  260. package/ios/ZCashLightClientKit/Synchronizer/Dependencies.swift +36 -9
  261. package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +401 -175
  262. package/ios/ZCashLightClientKit/Synchronizer.swift +192 -69
  263. package/ios/ZCashLightClientKit/Tool/DerivationTool.swift +69 -12
  264. package/ios/ZCashLightClientKit/Tor/TorClient.swift +502 -11
  265. package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +10 -6
  266. package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +24 -9
  267. package/ios/ZCashLightClientKit/Utils/SDKFlags.swift +71 -0
  268. package/ios/libzcashlc.xcframework/Info.plist +5 -5
  269. package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
  270. package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
  271. package/ios/zcashlc.h +1640 -378
  272. package/lib/rnzcash.rn.js.map +1 -1
  273. package/lib/src/react-native.d.ts +2 -2
  274. package/lib/src/types.d.ts +2 -0
  275. package/package.json +1 -1
  276. package/src/react-native.ts +2 -3
  277. package/src/types.ts +2 -0
@@ -10,8 +10,12 @@ import Foundation
10
10
  import Combine
11
11
 
12
12
  /// Synchronizer implementation for UIKit and iOS 13+
13
- // swiftlint:disable type_body_length
13
+ // swiftlint:disable type_body_length file_length
14
14
  public class SDKSynchronizer: Synchronizer {
15
+ private enum Constants {
16
+ static let fixWitnessesLastVersionCall = "ud_fixWitnessesLastVersionCall"
17
+ }
18
+
15
19
  public var alias: ZcashSynchronizerAlias { initializer.alias }
16
20
 
17
21
  private lazy var streamsUpdateQueue = { DispatchQueue(label: "streamsUpdateQueue_\(initializer.alias.description)") }()
@@ -27,7 +31,9 @@ public class SDKSynchronizer: Synchronizer {
27
31
 
28
32
  let metrics: SDKMetrics
29
33
  public let logger: Logger
30
- var tor: TorClient?
34
+ var exchangeRateTor: TorClient?
35
+ var httpTor: TorClient?
36
+ let sdkFlags: SDKFlags
31
37
 
32
38
  // Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead.
33
39
  private var underlyingStatus: GenericActor<InternalSyncStatus>
@@ -86,6 +92,7 @@ public class SDKSynchronizer: Synchronizer {
86
92
  self.syncSession = SyncSession(.nullID)
87
93
  self.syncSessionTicker = syncSessionTicker
88
94
  self.latestBlocksDataProvider = initializer.container.resolve(LatestBlocksDataProvider.self)
95
+ self.sdkFlags = initializer.container.resolve(SDKFlags.self)
89
96
 
90
97
  initializer.lightWalletService.connectionStateChange = { [weak self] oldState, newState in
91
98
  self?.connectivityStateChanged(oldState: oldState, newState: newState)
@@ -97,7 +104,6 @@ public class SDKSynchronizer: Synchronizer {
97
104
  }
98
105
 
99
106
  deinit {
100
- UsedAliasesChecker.stopUsing(alias: initializer.alias, id: initializer.id)
101
107
  Task { [blockProcessor] in
102
108
  await blockProcessor.stop()
103
109
  }
@@ -120,17 +126,15 @@ public class SDKSynchronizer: Synchronizer {
120
126
  return initialisationError
121
127
  }
122
128
 
123
- if !UsedAliasesChecker.tryToUse(alias: initializer.alias, id: initializer.id) {
124
- return .initializerAliasAlreadyInUse(initializer.alias)
125
- }
126
-
127
129
  return nil
128
130
  }
129
131
 
130
132
  public func prepare(
131
133
  with seed: [UInt8]?,
132
134
  walletBirthday: BlockHeight,
133
- for walletMode: WalletInitMode
135
+ for walletMode: WalletInitMode,
136
+ name: String,
137
+ keySource: String?
134
138
  ) async throws -> Initializer.InitializationResult {
135
139
  guard await status == .unprepared else { return .success }
136
140
 
@@ -138,7 +142,13 @@ public class SDKSynchronizer: Synchronizer {
138
142
  throw error
139
143
  }
140
144
 
141
- if case .seedRequired = try await self.initializer.initialize(with: seed, walletBirthday: walletBirthday, for: walletMode) {
145
+ if case .seedRequired = try await self.initializer.initialize(
146
+ with: seed,
147
+ walletBirthday: walletBirthday,
148
+ for: walletMode,
149
+ name: name,
150
+ keySource: keySource
151
+ ) {
142
152
  return .seedRequired
143
153
  }
144
154
 
@@ -147,6 +157,8 @@ public class SDKSynchronizer: Synchronizer {
147
157
 
148
158
  await updateStatus(.disconnected, updateExternalStatus: false)
149
159
 
160
+ await resolveWitnessesFix()
161
+
150
162
  return .success
151
163
  }
152
164
 
@@ -159,13 +171,42 @@ public class SDKSynchronizer: Synchronizer {
159
171
 
160
172
  case .syncing:
161
173
  logger.warn("warning: Synchronizer started when already running. Next sync process will be started when the current one stops.")
174
+ await exchangeRateTor?.wake()
175
+ await httpTor?.wake()
162
176
  /// This may look strange but `CompactBlockProcessor` has mechanisms which can handle this situation. So we are fine with calling
163
177
  /// it's start here.
164
178
  await blockProcessor.start(retry: retry)
165
179
 
166
180
  case .stopped, .synced, .disconnected, .error:
167
- let syncProgress = (try? await initializer.rustBackend.getWalletSummary()?.scanProgress?.progress()) ?? 0
168
- await updateStatus(.syncing(syncProgress))
181
+ let walletSummary = try? await initializer.rustBackend.getWalletSummary()
182
+ let recoveryProgress = walletSummary?.recoveryProgress
183
+
184
+ var syncProgress: Float = 0.0
185
+ var areFundsSpendable = false
186
+
187
+ if let scanProgress = walletSummary?.scanProgress {
188
+ let composedNumerator = Float(scanProgress.numerator) + Float(recoveryProgress?.numerator ?? 0)
189
+ let composedDenominator = Float(scanProgress.denominator) + Float(recoveryProgress?.denominator ?? 0)
190
+
191
+ let progress: Float
192
+ if composedDenominator == 0 {
193
+ progress = 1.0
194
+ } else {
195
+ progress = composedNumerator / composedDenominator
196
+ }
197
+
198
+ // this shouldn't happen but if it does, we need to get notified by clients and work on a fix
199
+ if progress > 1.0 {
200
+ throw ZcashError.rustScanProgressOutOfRange("\(progress)")
201
+ }
202
+
203
+ areFundsSpendable = scanProgress.isComplete
204
+
205
+ syncProgress = progress
206
+ }
207
+ await updateStatus(.syncing(syncProgress, areFundsSpendable))
208
+ await exchangeRateTor?.wake()
209
+ await httpTor?.wake()
169
210
  await blockProcessor.start(retry: retry)
170
211
  }
171
212
  }
@@ -176,6 +217,8 @@ public class SDKSynchronizer: Synchronizer {
176
217
  // downloading is really done. Which could block execution of the code on the client side. So it's better strategy to spin up new task and
177
218
  // exit fast on client side.
178
219
  Task(priority: .high) {
220
+ await sdkFlags.sdkStopped()
221
+
179
222
  let status = await self.status
180
223
  guard status != .stopped, status != .disconnected else {
181
224
  logger.info("attempted to stop when status was: \(status)")
@@ -183,7 +226,27 @@ public class SDKSynchronizer: Synchronizer {
183
226
  }
184
227
 
185
228
  await blockProcessor.stop()
229
+ await exchangeRateTor?.sleep()
230
+ await httpTor?.sleep()
231
+ }
232
+ }
233
+
234
+ // MARK: Witnesses Fix
235
+
236
+ private func resolveWitnessesFix() async {
237
+ let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
238
+
239
+ guard let lastVersionCall = UserDefaults.standard.object(forKey: Constants.fixWitnessesLastVersionCall) as? String else {
240
+ UserDefaults.standard.set(appVersion, forKey: Constants.fixWitnessesLastVersionCall)
241
+ await initializer.rustBackend.fixWitnesses()
242
+ return
243
+ }
244
+
245
+ guard lastVersionCall < appVersion else {
246
+ return
186
247
  }
248
+
249
+ await initializer.rustBackend.fixWitnesses()
187
250
  }
188
251
 
189
252
  // MARK: Connectivity State
@@ -213,8 +276,8 @@ public class SDKSynchronizer: Synchronizer {
213
276
  // log reorg information
214
277
  self?.logger.info("handling reorg at: \(reorgHeight) with rewind height: \(rewindHeight)")
215
278
 
216
- case let .progressUpdated(progress):
217
- await self?.progressUpdated(progress: progress)
279
+ case let .progressUpdated(syncProgress, areFundsSpendable):
280
+ await self?.progressUpdated(syncProgress, areFundsSpendable)
218
281
 
219
282
  case .syncProgress:
220
283
  break
@@ -247,13 +310,15 @@ public class SDKSynchronizer: Synchronizer {
247
310
  }
248
311
 
249
312
  private func foundTransactions(transactions: [ZcashTransaction.Overview], in range: CompactBlockRange) {
313
+ guard !transactions.isEmpty else { return }
314
+
250
315
  streamsUpdateQueue.async { [weak self] in
251
316
  self?.eventSubject.send(.foundTransactions(transactions, range))
252
317
  }
253
318
  }
254
319
 
255
- private func progressUpdated(progress: Float) async {
256
- let newStatus = InternalSyncStatus(progress)
320
+ private func progressUpdated(_ syncProgress: Float, _ areFundsSpendable: Bool) async {
321
+ let newStatus = InternalSyncStatus(syncProgress, areFundsSpendable)
257
322
  await updateStatus(newStatus)
258
323
  }
259
324
 
@@ -265,7 +330,47 @@ public class SDKSynchronizer: Synchronizer {
265
330
 
266
331
  // MARK: Synchronizer methods
267
332
 
268
- public func proposeTransfer(accountIndex: Int, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal {
333
+ public func listAccounts() async throws -> [Account] {
334
+ try await initializer.rustBackend.listAccounts()
335
+ }
336
+
337
+ // swiftlint:disable:next function_parameter_count
338
+ public func importAccount(
339
+ ufvk: String,
340
+ seedFingerprint: [UInt8]?,
341
+ zip32AccountIndex: Zip32AccountIndex?,
342
+ purpose: AccountPurpose,
343
+ name: String,
344
+ keySource: String?
345
+ ) async throws -> AccountUUID {
346
+ // called when a new account is imported
347
+ let chainTip = try? await UInt32(
348
+ initializer.lightWalletService.latestBlockHeight(
349
+ mode: await sdkFlags.ifTor(.uniqueTor)
350
+ )
351
+ )
352
+
353
+ let checkpointSource = initializer.container.resolve(CheckpointSource.self)
354
+
355
+ guard let chainTip else {
356
+ throw ZcashError.synchronizerNotPrepared
357
+ }
358
+
359
+ let checkpoint = checkpointSource.birthday(for: BlockHeight(chainTip))
360
+
361
+ return try await initializer.rustBackend.importAccount(
362
+ ufvk: ufvk,
363
+ seedFingerprint: seedFingerprint,
364
+ zip32AccountIndex: zip32AccountIndex,
365
+ treeState: checkpoint.treeState(),
366
+ recoverUntil: chainTip,
367
+ purpose: purpose,
368
+ name: name,
369
+ keySource: keySource
370
+ )
371
+ }
372
+
373
+ public func proposeTransfer(accountUUID: AccountUUID, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal {
269
374
  try throwIfUnprepared()
270
375
 
271
376
  if case Recipient.transparent = recipient, memo != nil {
@@ -273,7 +378,7 @@ public class SDKSynchronizer: Synchronizer {
273
378
  }
274
379
 
275
380
  let proposal = try await transactionEncoder.proposeTransfer(
276
- accountIndex: accountIndex,
381
+ accountUUID: accountUUID,
277
382
  recipient: recipient.stringEncoded,
278
383
  amount: amount,
279
384
  memoBytes: memo?.asMemoBytes()
@@ -283,7 +388,7 @@ public class SDKSynchronizer: Synchronizer {
283
388
  }
284
389
 
285
390
  public func proposeShielding(
286
- accountIndex: Int,
391
+ accountUUID: AccountUUID,
287
392
  shieldingThreshold: Zatoshi,
288
393
  memo: Memo,
289
394
  transparentReceiver: TransparentAddress? = nil
@@ -291,7 +396,7 @@ public class SDKSynchronizer: Synchronizer {
291
396
  try throwIfUnprepared()
292
397
 
293
398
  return try await transactionEncoder.proposeShielding(
294
- accountIndex: accountIndex,
399
+ accountUUID: accountUUID,
295
400
  shieldingThreshold: shieldingThreshold,
296
401
  memoBytes: memo.asMemoBytes(),
297
402
  transparentReceiver: transparentReceiver?.stringEncoded
@@ -300,13 +405,13 @@ public class SDKSynchronizer: Synchronizer {
300
405
 
301
406
  public func proposefulfillingPaymentURI(
302
407
  _ uri: String,
303
- accountIndex: Int
408
+ accountUUID: AccountUUID
304
409
  ) async throws -> Proposal {
305
410
  do {
306
411
  try throwIfUnprepared()
307
412
  return try await transactionEncoder.proposeFulfillingPaymentFromURI(
308
413
  uri,
309
- accountIndex: accountIndex
414
+ accountUUID: accountUUID
310
415
  )
311
416
  } catch ZcashError.rustCreateToAddress(let error) {
312
417
  throw ZcashError.rustProposeTransferFromURI(error)
@@ -333,9 +438,19 @@ public class SDKSynchronizer: Synchronizer {
333
438
  proposal: proposal,
334
439
  spendingKey: spendingKey
335
440
  )
441
+
442
+ return submitTransactions(transactions)
443
+ }
444
+
445
+ func submitTransactions(_ transactions: [ZcashTransaction.Overview]) -> AsyncThrowingStream<TransactionSubmitResult, Error> {
336
446
  var iterator = transactions.makeIterator()
337
447
  var submitFailed = false
338
448
 
449
+ // let clients know the transaction repository changed
450
+ if !transactions.isEmpty {
451
+ eventSubject.send(.foundTransactions(transactions, nil))
452
+ }
453
+
339
454
  return AsyncThrowingStream() {
340
455
  guard let transaction = iterator.next() else { return nil }
341
456
 
@@ -357,19 +472,30 @@ public class SDKSynchronizer: Synchronizer {
357
472
  }
358
473
  }
359
474
  }
475
+
476
+ public func createPCZTFromProposal(accountUUID: AccountUUID, proposal: Proposal) async throws -> Pczt {
477
+ try await initializer.rustBackend.createPCZTFromProposal(
478
+ accountUUID: accountUUID,
479
+ proposal: proposal.inner
480
+ )
481
+ }
360
482
 
361
- public func sendToAddress(
362
- spendingKey: UnifiedSpendingKey,
363
- zatoshi: Zatoshi,
364
- toAddress: Recipient,
365
- memo: Memo?
366
- ) async throws -> ZcashTransaction.Overview {
367
- try throwIfUnprepared()
483
+ public func redactPCZTForSigner(pczt: Pczt) async throws -> Pczt {
484
+ try await initializer.rustBackend.redactPCZTForSigner(
485
+ pczt: pczt
486
+ )
487
+ }
368
488
 
369
- if case Recipient.transparent = toAddress, memo != nil {
370
- throw ZcashError.synchronizerSendMemoToTransparentAddress
371
- }
489
+ public func PCZTRequiresSaplingProofs(pczt: Pczt) async -> Bool {
490
+ await initializer.rustBackend.PCZTRequiresSaplingProofs(
491
+ pczt: pczt
492
+ )
493
+ }
372
494
 
495
+ public func addProofsToPCZT(pczt: Pczt) async throws -> Pczt {
496
+ // TODO [#1724]: zcash_client_backend: Make Sapling parameters optional for extract_and_store_transaction
497
+ // TODO [#1724]: https://github.com/zcash/librustzcash/issues/1724
498
+ // if await initializer.rustBackend.PCZTRequiresSaplingProofs(pczt: pczt) {
373
499
  try await SaplingParameterDownloader.downloadParamsIfnotPresent(
374
500
  spendURL: initializer.spendParamsURL,
375
501
  spendSourceURL: initializer.saplingParamsSourceURL.spendParamFileURL,
@@ -377,108 +503,75 @@ public class SDKSynchronizer: Synchronizer {
377
503
  outputSourceURL: initializer.saplingParamsSourceURL.outputParamFileURL,
378
504
  logger: logger
379
505
  )
506
+ // }
380
507
 
381
- return try await createToAddress(
382
- spendingKey: spendingKey,
383
- zatoshi: zatoshi,
384
- recipient: toAddress,
385
- memo: memo
508
+ return try await initializer.rustBackend.addProofsToPCZT(
509
+ pczt: pczt
386
510
  )
387
511
  }
388
-
389
- public func shieldFunds(
390
- spendingKey: UnifiedSpendingKey,
391
- memo: Memo,
392
- shieldingThreshold: Zatoshi
393
- ) async throws -> ZcashTransaction.Overview {
512
+
513
+ public func createTransactionFromPCZT(pcztWithProofs: Pczt, pcztWithSigs: Pczt) async throws -> AsyncThrowingStream<TransactionSubmitResult, Error> {
394
514
  try throwIfUnprepared()
395
515
 
396
- // let's see if there are funds to shield
397
- let accountIndex = Int(spendingKey.account)
398
-
399
- guard let tBalance = try await self.getAccountBalance(accountIndex: accountIndex)?.unshielded else {
400
- throw ZcashError.synchronizerSpendingKeyDoesNotBelongToTheWallet
401
- }
402
-
403
- // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet.
404
- guard tBalance >= self.network.constants.defaultFee() else {
405
- throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds
406
- }
407
-
408
- guard let proposal = try await transactionEncoder.proposeShielding(
409
- accountIndex: Int(spendingKey.account),
410
- shieldingThreshold: shieldingThreshold,
411
- memoBytes: memo.asMemoBytes(),
412
- transparentReceiver: nil
413
- ) else { throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds }
414
-
415
- let transactions = try await transactionEncoder.createProposedTransactions(
416
- proposal: proposal,
417
- spendingKey: spendingKey
516
+ try await SaplingParameterDownloader.downloadParamsIfnotPresent(
517
+ spendURL: initializer.spendParamsURL,
518
+ spendSourceURL: initializer.saplingParamsSourceURL.spendParamFileURL,
519
+ outputURL: initializer.outputParamsURL,
520
+ outputSourceURL: initializer.saplingParamsSourceURL.outputParamFileURL,
521
+ logger: logger
418
522
  )
419
523
 
420
- assert(transactions.count == 1, "Rust backend doesn't produce multiple transactions yet")
421
- let transaction = transactions[0]
422
-
423
- let encodedTx = try transaction.encodedTransaction()
424
-
425
- try await transactionEncoder.submit(transaction: encodedTx)
524
+ let txId = try await initializer.rustBackend.extractAndStoreTxFromPCZT(
525
+ pcztWithProofs: pcztWithProofs,
526
+ pcztWithSigs: pcztWithSigs
527
+ )
426
528
 
427
- return transaction
529
+ let transactions = try await transactionEncoder.fetchTransactionsForTxIds([txId])
530
+
531
+ return submitTransactions(transactions)
428
532
  }
429
533
 
430
- func createToAddress(
431
- spendingKey: UnifiedSpendingKey,
432
- zatoshi: Zatoshi,
433
- recipient: Recipient,
434
- memo: Memo?
435
- ) async throws -> ZcashTransaction.Overview {
436
- do {
437
- if
438
- case .transparent = recipient,
439
- memo != nil {
440
- throw ZcashError.synchronizerSendMemoToTransparentAddress
441
- }
442
-
443
- let proposal = try await transactionEncoder.proposeTransfer(
444
- accountIndex: Int(spendingKey.account),
445
- recipient: recipient.stringEncoded,
446
- amount: zatoshi,
447
- memoBytes: memo?.asMemoBytes()
448
- )
449
-
450
- let transactions = try await transactionEncoder.createProposedTransactions(
451
- proposal: proposal,
452
- spendingKey: spendingKey
453
- )
454
-
455
- assert(transactions.count == 1, "Rust backend doesn't produce multiple transactions yet")
456
- let transaction = transactions[0]
457
-
458
- let encodedTransaction = try transaction.encodedTransaction()
459
-
460
- try await transactionEncoder.submit(transaction: encodedTransaction)
461
-
462
- return transaction
463
- } catch {
464
- throw error
465
- }
534
+ public func fetchTxidsWithMemoContaining(searchTerm: String) async throws -> [Data] {
535
+ try await transactionRepository.fetchTxidsWithMemoContaining(searchTerm: searchTerm)
466
536
  }
467
-
537
+
468
538
  public func allReceivedTransactions() async throws -> [ZcashTransaction.Overview] {
469
- try await transactionRepository.findReceived(offset: 0, limit: Int.max)
539
+ try await enhanceRawTransactionsWithState(
540
+ rawTransactions: try await transactionRepository.findReceived(offset: 0, limit: Int.max)
541
+ )
470
542
  }
471
543
 
472
544
  public func allTransactions() async throws -> [ZcashTransaction.Overview] {
473
- return try await transactionRepository.find(offset: 0, limit: Int.max, kind: .all)
545
+ try await enhanceRawTransactionsWithState(
546
+ rawTransactions: try await transactionRepository.find(offset: 0, limit: Int.max, kind: .all)
547
+ )
474
548
  }
475
549
 
476
550
  public func allSentTransactions() async throws -> [ZcashTransaction.Overview] {
477
- return try await transactionRepository.findSent(offset: 0, limit: Int.max)
551
+ try await enhanceRawTransactionsWithState(
552
+ rawTransactions: try await transactionRepository.findSent(offset: 0, limit: Int.max)
553
+ )
478
554
  }
479
555
 
480
556
  public func allTransactions(from transaction: ZcashTransaction.Overview, limit: Int) async throws -> [ZcashTransaction.Overview] {
481
- return try await transactionRepository.find(from: transaction, limit: limit, kind: .all)
557
+ try await enhanceRawTransactionsWithState(
558
+ rawTransactions: try await transactionRepository.find(from: transaction, limit: limit, kind: .all)
559
+ )
560
+ }
561
+
562
+ private func enhanceRawTransactionsWithState(rawTransactions: [ZcashTransaction.Overview]) async throws -> [ZcashTransaction.Overview] {
563
+ var latestKnownBlockHeight = await latestBlocksDataProvider.latestBlockHeight
564
+ if latestKnownBlockHeight == 0 {
565
+ latestKnownBlockHeight = try await initializer.rustBackend.maxScannedHeight() ?? .zero
566
+ }
567
+
568
+ return rawTransactions.map { rawTransaction in
569
+ var copyOfRawTransaction = rawTransaction
570
+
571
+ copyOfRawTransaction.state = rawTransaction.getState(for: latestKnownBlockHeight)
572
+
573
+ return copyOfRawTransaction
574
+ }
482
575
  }
483
576
 
484
577
  public func paginatedTransactions(of kind: TransactionKind = .all) -> PaginatedTransactionRepository {
@@ -502,7 +595,7 @@ public class SDKSynchronizer: Synchronizer {
502
595
  }
503
596
 
504
597
  public func latestHeight() async throws -> BlockHeight {
505
- try await blockProcessor.latestHeight()
598
+ try await blockProcessor.latestHeight(mode: await sdkFlags.ifTor(.torInGroup("SDKSynchronizer.latestHeight")))
506
599
  }
507
600
 
508
601
  public func refreshUTXOs(address: TransparentAddress, from height: BlockHeight) async throws -> RefreshedUTXOs {
@@ -510,55 +603,65 @@ public class SDKSynchronizer: Synchronizer {
510
603
  return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height)
511
604
  }
512
605
 
513
- public func getAccountBalance(accountIndex: Int = 0) async throws -> AccountBalance? {
514
- try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]
606
+ public func getAccountsBalances() async throws -> [AccountUUID: AccountBalance] {
607
+ try await initializer.rustBackend.getWalletSummary()?.accountBalances ?? [:]
515
608
  }
516
609
 
517
610
  /// Fetches the latest ZEC-USD exchange rate.
518
611
  public func refreshExchangeRateUSD() {
519
- // ignore refresh request when one is already in flight
520
- if let latestState = tor?.cachedFiatCurrencyResult?.state, latestState == .fetching {
521
- return
522
- }
523
-
524
- // broadcast cached value but update the state
525
- if let cachedFiatCurrencyResult = tor?.cachedFiatCurrencyResult {
526
- var fetchingState = cachedFiatCurrencyResult
527
- fetchingState.state = .fetching
528
- tor?.cachedFiatCurrencyResult = fetchingState
529
-
530
- exchangeRateUSDSubject.send(fetchingState)
531
- }
532
-
533
612
  Task {
613
+ // ignore when Tor is not enabled
614
+ guard await sdkFlags.exchangeRateEnabled else {
615
+ return
616
+ }
617
+
618
+ // ignore refresh request when one is already in flight
619
+ if let latestState = await exchangeRateTor?.cachedFiatCurrencyResult?.state, latestState == .fetching {
620
+ return
621
+ }
622
+
623
+ // broadcast cached value but update the state
624
+ if let cachedFiatCurrencyResult = await exchangeRateTor?.cachedFiatCurrencyResult {
625
+ var fetchingState = cachedFiatCurrencyResult
626
+ fetchingState.state = .fetching
627
+ await exchangeRateTor?.updateCachedFiatCurrencyResult(fetchingState)
628
+
629
+ exchangeRateUSDSubject.send(fetchingState)
630
+ }
631
+
534
632
  do {
535
- if tor == nil {
633
+ if exchangeRateTor == nil {
536
634
  logger.info("Bootstrapping Tor client for fetching exchange rates")
537
- tor = try await TorClient(torDir: initializer.torDirURL)
635
+ let torClient = initializer.container.resolve(TorClient.self)
636
+ exchangeRateTor = try await torClient.isolatedClient()
538
637
  }
539
638
  // broadcast new value in case of success
540
- exchangeRateUSDSubject.send(try await tor?.getExchangeRateUSD())
639
+ exchangeRateUSDSubject.send(try await exchangeRateTor?.getExchangeRateUSD())
541
640
  } catch {
542
641
  // broadcast cached value but update the state
543
- var errorState = tor?.cachedFiatCurrencyResult
642
+ var errorState = await exchangeRateTor?.cachedFiatCurrencyResult
544
643
  errorState?.state = .error
545
- tor?.cachedFiatCurrencyResult = errorState
546
-
644
+ await exchangeRateTor?.updateCachedFiatCurrencyResult(errorState)
645
+
547
646
  exchangeRateUSDSubject.send(errorState)
548
647
  }
549
648
  }
550
649
  }
551
650
 
552
- public func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
553
- try await blockProcessor.getUnifiedAddress(accountIndex: accountIndex)
651
+ public func getUnifiedAddress(accountUUID: AccountUUID) async throws -> UnifiedAddress {
652
+ try await blockProcessor.getUnifiedAddress(accountUUID: accountUUID)
653
+ }
654
+
655
+ public func getSaplingAddress(accountUUID: AccountUUID) async throws -> SaplingAddress {
656
+ try await blockProcessor.getSaplingAddress(accountUUID: accountUUID)
554
657
  }
555
658
 
556
- public func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress {
557
- try await blockProcessor.getSaplingAddress(accountIndex: accountIndex)
659
+ public func getTransparentAddress(accountUUID: AccountUUID) async throws -> TransparentAddress {
660
+ try await blockProcessor.getTransparentAddress(accountUUID: accountUUID)
558
661
  }
559
662
 
560
- public func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
561
- try await blockProcessor.getTransparentAddress(accountIndex: accountIndex)
663
+ public func getCustomUnifiedAddress(accountUUID: AccountUUID, receivers: Set<ReceiverType>) async throws -> UnifiedAddress {
664
+ try await blockProcessor.getCustomUnifiedAddress(accountUUID: accountUUID, receivers: receivers)
562
665
  }
563
666
 
564
667
  // MARK: Rewind
@@ -660,9 +763,9 @@ public class SDKSynchronizer: Synchronizer {
660
763
  /// - nBlocksToFetch: The number of blocks expected to be downloaded from the stream, with the time compared to `fetchThresholdSeconds`. The default is 100.
661
764
  /// - kServers: The expected number of endpoints in the output. The default is 3.
662
765
  /// - network: Mainnet or testnet. The default is mainnet.
766
+ // swiftlint:disable:next cyclomatic_complexity
663
767
  public func evaluateBestOf(
664
768
  endpoints: [LightWalletEndpoint],
665
- latencyThresholdMillis: Double = 300.0,
666
769
  fetchThresholdSeconds: Double = 60.0,
667
770
  nBlocksToFetch: UInt64 = 100,
668
771
  kServers: Int = 3,
@@ -685,31 +788,33 @@ public class SDKSynchronizer: Synchronizer {
685
788
  var blockTime: TimeInterval
686
789
  }
687
790
 
791
+ let torClient = initializer.container.resolve(TorClient.self)
792
+
688
793
  // Initialize services for the endpoints
689
794
  let services = endpoints.map {
690
795
  Service(
691
796
  originalEndpoint: $0,
692
- service: LightWalletGRPCService(
693
- host: $0.host,
694
- port: $0.port,
695
- secure: $0.secure,
696
- singleCallTimeout: 5000,
697
- streamingCallTimeout: Int64(fetchThresholdSeconds) * 1000
698
- ),
797
+ service: LightWalletGRPCServiceOverTor(endpoint: $0, tor: torClient),
699
798
  url: "\($0.host):\($0.port)"
700
799
  )
701
800
  }
702
801
 
703
802
  // Parallel part
704
803
  var checkResults: [String: CheckResult] = [:]
804
+ let sdkFlagsRef = sdkFlags
705
805
 
706
806
  await withTaskGroup(of: CheckResult.self) { group in
707
807
  for service in services {
708
808
  group.addTask {
709
809
  let startTime = Date().timeIntervalSince1970
710
- let info = try? await service.service.getInfo()
810
+
811
+ // called when performance of servers is evaluated
812
+ let mode = await sdkFlagsRef.ifTor(ServiceMode.torInGroup("SDKSynchronizer.evaluateBestOf(\(service.originalEndpoint))"))
813
+
814
+ let info = try? await service.service.getInfo(mode: mode)
711
815
  let markTime = Date().timeIntervalSince1970
712
- let latestBlockHeight = try? await service.service.latestBlockHeight()
816
+ // called when performance of servers is evaluated
817
+ let latestBlockHeight = try? await service.service.latestBlockHeight(mode: mode)
713
818
  let endTime = Date().timeIntervalSince1970
714
819
 
715
820
  let getInfoTime = markTime - startTime
@@ -738,7 +843,7 @@ public class SDKSynchronizer: Synchronizer {
738
843
  }
739
844
 
740
845
  // rule out if mismatch of networks
741
- guard (info.chainName == "main" && network == .mainnet)
846
+ guard (info.chainName == "main" && network == .mainnet)
742
847
  || (info.chainName == "test" && network == .testnet) else {
743
848
  continue
744
849
  }
@@ -767,20 +872,15 @@ public class SDKSynchronizer: Synchronizer {
767
872
  tmpResults[result.id] = result
768
873
  }
769
874
 
770
- // rule out all means above latencyThreshold
771
- let underThreshold = tmpResults.compactMap {
772
- $0.value.mean < (latencyThresholdMillis / 1000.0) ? $0 : nil
773
- }
774
-
775
875
  // sort the server responses by mean
776
- let sortedUnderThreshold = underThreshold.sorted {
876
+ let sortedCheckResults = tmpResults.sorted {
777
877
  $0.value.mean < $1.value.mean
778
878
  }
779
879
 
780
- // retain only k servers
781
- let sortedUnderThresholdKOnly = sortedUnderThreshold.prefix(3)
880
+ // retain k servers
881
+ let sortedKOnly = sortedCheckResults.prefix(kServers)
782
882
 
783
- sortedUnderThresholdKOnly.forEach {
883
+ sortedKOnly.forEach {
784
884
  checkResults[$0.key] = $0.value
785
885
  }
786
886
  }
@@ -798,10 +898,15 @@ public class SDKSynchronizer: Synchronizer {
798
898
  guard info.blockHeight >= nBlocksToFetch else {
799
899
  continue
800
900
  }
801
-
802
- let stream = service.service.blockStream(startHeight: BlockHeight(info.blockHeight - nBlocksToFetch), endHeight: BlockHeight(info.blockHeight))
803
-
901
+
804
902
  do {
903
+ // Fetched the same way as in `BlockDownloader`.
904
+ let stream = try service.service.blockStream(
905
+ startHeight: BlockHeight(info.blockHeight - nBlocksToFetch),
906
+ endHeight: BlockHeight(info.blockHeight),
907
+ mode: .direct
908
+ )
909
+
805
910
  let startTime = Date().timeIntervalSince1970
806
911
  var endTime = startTime
807
912
  for try await _ in stream {
@@ -837,6 +942,130 @@ public class SDKSynchronizer: Synchronizer {
837
942
  return finalResult
838
943
  }
839
944
 
945
+ public func estimateBirthdayHeight(for date: Date) -> BlockHeight {
946
+ initializer.container.resolve(CheckpointSource.self).estimateBirthdayHeight(for: date)
947
+ }
948
+
949
+ public func tor(enabled: Bool) async throws {
950
+ let isExchangeRateEnabled = await sdkFlags.exchangeRateEnabled
951
+
952
+ // turn Tor on
953
+ if enabled && !isExchangeRateEnabled {
954
+ try await enableAndStartupTorClient()
955
+ }
956
+
957
+ // turn Tor off
958
+ if !enabled && !isExchangeRateEnabled {
959
+ try await disableAndCleanupTorClients()
960
+ }
961
+
962
+ await sdkFlags.torFlagUpdate(enabled)
963
+ }
964
+
965
+ public func exchangeRateOverTor(enabled: Bool) async throws {
966
+ let isTorEnabled = await sdkFlags.torEnabled
967
+
968
+ // turn Tor on
969
+ if enabled && !isTorEnabled {
970
+ try await enableAndStartupTorClient()
971
+ }
972
+
973
+ // turn Tor off
974
+ if !enabled && !isTorEnabled {
975
+ try await disableAndCleanupTorClients()
976
+ }
977
+
978
+ await sdkFlags.exchangeRateFlagUpdate(enabled)
979
+ }
980
+
981
+ private func enableAndStartupTorClient() async throws {
982
+ let torClient = initializer.container.resolve(TorClient.self)
983
+ try await torClient.prepare()
984
+ }
985
+
986
+ private func disableAndCleanupTorClients() async throws {
987
+ await sdkFlags.torClientInitializationSuccessfullyDoneFlagUpdate(nil)
988
+
989
+ // case when previous was enabled and newly is required to be stopped
990
+ let torClient = initializer.container.resolve(TorClient.self)
991
+ // close of the initial TorClient, it's used for creation of isolated clients
992
+ try await torClient.close()
993
+ // deinit of isolated TorClient used for fetching exchange rates
994
+ exchangeRateTor = nil
995
+ // deinit of isolated TorClient used for http requests
996
+ httpTor = nil
997
+ // close all connections
998
+ let lwdService = initializer.container.resolve(LightWalletService.self)
999
+ await lwdService.closeConnections()
1000
+ }
1001
+
1002
+ public func isTorSuccessfullyInitialized() async -> Bool? {
1003
+ await sdkFlags.torClientInitializationSuccessfullyDone
1004
+ }
1005
+
1006
+ public func httpRequestOverTor(for request: URLRequest, retryLimit: UInt8 = 3) async throws -> (data: Data, response: HTTPURLResponse) {
1007
+ guard await sdkFlags.torEnabled else {
1008
+ throw ZcashError.torNotEnabled
1009
+ }
1010
+
1011
+ if httpTor == nil {
1012
+ logger.info("Bootstrapping Tor client for making http requests")
1013
+ if let torService = initializer.container.resolve(LightWalletService.self) as? LightWalletGRPCServiceOverTor {
1014
+ httpTor = try await torService.tor.isolatedClient()
1015
+ }
1016
+ }
1017
+
1018
+ guard let httpTor else {
1019
+ throw ZcashError.torClientUnavailable
1020
+ }
1021
+
1022
+ return try await httpTor.isolatedClient().httpRequest(for: request, retryLimit: retryLimit)
1023
+ }
1024
+
1025
+ public func debugDatabase(sql: String) -> String {
1026
+ transactionRepository.debugDatabase(sql: sql)
1027
+ }
1028
+
1029
+ public func getSingleUseTransparentAddress(accountUUID: AccountUUID) async throws -> SingleUseTransparentAddress {
1030
+ try await initializer.rustBackend.getSingleUseTransparentAddress(accountUUID: accountUUID)
1031
+ }
1032
+
1033
+ public func checkSingleUseTransparentAddresses(accountUUID: AccountUUID) async throws -> TransparentAddressCheckResult {
1034
+ let dbData = initializer.dataDbURL.osStr()
1035
+
1036
+ return try await initializer.lightWalletService.checkSingleUseTransparentAddresses(
1037
+ dbData: dbData,
1038
+ networkType: network.networkType,
1039
+ accountUUID: accountUUID,
1040
+ mode: await sdkFlags.ifTor(.uniqueTor)
1041
+ )
1042
+ }
1043
+
1044
+ public func updateTransparentAddressTransactions(address: String) async throws -> TransparentAddressCheckResult {
1045
+ let dbData = initializer.dataDbURL.osStr()
1046
+
1047
+ return try await initializer.lightWalletService.updateTransparentAddressTransactions(
1048
+ address: address,
1049
+ start: 0,
1050
+ end: -1,
1051
+ dbData: dbData,
1052
+ networkType: network.networkType,
1053
+ mode: await sdkFlags.ifTor(.uniqueTor)
1054
+ )
1055
+ }
1056
+
1057
+ public func fetchUTXOsBy(address: String, accountUUID: AccountUUID) async throws -> TransparentAddressCheckResult {
1058
+ let dbData = initializer.dataDbURL.osStr()
1059
+
1060
+ return try await initializer.lightWalletService.fetchUTXOsByAddress(
1061
+ address: address,
1062
+ dbData: dbData,
1063
+ networkType: network.networkType,
1064
+ accountUUID: accountUUID,
1065
+ mode: await sdkFlags.ifTor(.uniqueTor)
1066
+ )
1067
+ }
1068
+
840
1069
  // MARK: Server switch
841
1070
 
842
1071
  public func switchTo(endpoint: LightWalletEndpoint) async throws {
@@ -846,16 +1075,12 @@ public class SDKSynchronizer: Synchronizer {
846
1075
  await blockProcessor.stop()
847
1076
  }
848
1077
 
1078
+ let torClient = initializer.container.resolve(TorClient.self)
1079
+
849
1080
  // Validation of the server is first because any custom endpoint can be passed here
850
- // Extra instance of the service is created with lower timeout ofr a single call
1081
+ // Extra instance of the service is created with lower timeout for a single call
851
1082
  initializer.container.register(type: LightWalletService.self, isSingleton: true) { _ in
852
- LightWalletGRPCService(
853
- host: endpoint.host,
854
- port: endpoint.port,
855
- secure: endpoint.secure,
856
- singleCallTimeout: 5000,
857
- streamingCallTimeout: endpoint.streamingCallTimeoutInMillis
858
- )
1083
+ LightWalletGRPCServiceOverTor(endpoint: endpoint, tor: torClient, singleCallTimeout: 5000)
859
1084
  }
860
1085
 
861
1086
  let validateSever = ValidateServerAction(
@@ -876,7 +1101,7 @@ public class SDKSynchronizer: Synchronizer {
876
1101
 
877
1102
  // LightWalletService dependency update
878
1103
  initializer.container.register(type: LightWalletService.self, isSingleton: true) { _ in
879
- LightWalletGRPCService(endpoint: endpoint)
1104
+ LightWalletGRPCServiceOverTor(endpoint: endpoint, tor: torClient)
880
1105
  }
881
1106
 
882
1107
  // DEPENDENCIES
@@ -893,8 +1118,9 @@ public class SDKSynchronizer: Synchronizer {
893
1118
  initializer.container.register(type: LatestBlocksDataProvider.self, isSingleton: true) { di in
894
1119
  let service = di.resolve(LightWalletService.self)
895
1120
  let rustBackend = di.resolve(ZcashRustBackendWelding.self)
1121
+ let sdkFlags = di.resolve(SDKFlags.self)
896
1122
 
897
- return LatestBlocksDataProviderImpl(service: service, rustBackend: rustBackend)
1123
+ return LatestBlocksDataProviderImpl(service: service, rustBackend: rustBackend, sdkFlags: sdkFlags)
898
1124
  }
899
1125
 
900
1126
  // CompactBlockProcessor dependency update
@@ -925,7 +1151,7 @@ public class SDKSynchronizer: Synchronizer {
925
1151
  private func snapshotState(status: InternalSyncStatus) async -> SynchronizerState {
926
1152
  await SynchronizerState(
927
1153
  syncSessionID: syncSession.value,
928
- accountBalance: try? await getAccountBalance(),
1154
+ accountsBalances: (try? await getAccountsBalances()) ?? [:],
929
1155
  internalSyncStatus: status,
930
1156
  latestBlockHeight: latestBlocksDataProvider.latestBlockHeight
931
1157
  )