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
@@ -29,7 +29,8 @@ extension UpdateSubtreeRootsAction: Action {
29
29
  request.shieldedProtocol = .sapling
30
30
 
31
31
  logger.debug("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
32
- let stream = service.getSubtreeRoots(request)
32
+ // ServiceMode to resolve
33
+ let stream = try service.getSubtreeRoots(request, mode: .direct)
33
34
 
34
35
  var saplingRoots: [SubtreeRoot] = []
35
36
 
@@ -59,7 +60,8 @@ extension UpdateSubtreeRootsAction: Action {
59
60
  var orchardRequest = GetSubtreeRootsArg()
60
61
  orchardRequest.shieldedProtocol = .orchard
61
62
 
62
- let stream = service.getSubtreeRoots(orchardRequest)
63
+ // ServiceMode to resolve
64
+ let stream = try service.getSubtreeRoots(orchardRequest, mode: .direct)
63
65
 
64
66
  var orchardRoots: [SubtreeRoot] = []
65
67
 
@@ -11,11 +11,13 @@ final class ValidateServerAction {
11
11
  let configProvider: CompactBlockProcessor.ConfigProvider
12
12
  let rustBackend: ZcashRustBackendWelding
13
13
  var service: LightWalletService
14
+ let sdkFlags: SDKFlags
14
15
 
15
16
  init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
16
17
  self.configProvider = configProvider
17
18
  rustBackend = container.resolve(ZcashRustBackendWelding.self)
18
19
  service = container.resolve(LightWalletService.self)
20
+ sdkFlags = container.resolve(SDKFlags.self)
19
21
  }
20
22
  }
21
23
 
@@ -24,7 +26,8 @@ extension ValidateServerAction: Action {
24
26
 
25
27
  func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
26
28
  let config = await configProvider.config
27
- let info = try await service.getInfo()
29
+ // called each sync, an action in a state machine diagram
30
+ let info = try await service.getInfo(mode: await sdkFlags.ifTor(.defaultTor))
28
31
  let localNetwork = config.network
29
32
  let saplingActivation = config.saplingActivation
30
33
 
@@ -20,6 +20,7 @@ actor CompactBlockProcessor {
20
20
  private var eventClosures: [String: EventClosure] = [:]
21
21
 
22
22
  private var syncTask: Task<Void, Error>?
23
+ private var mempoolDetectionTask: Task<Void, Error>?
23
24
 
24
25
  private let actions: [CBPState: Action]
25
26
  var context: ActionContext
@@ -67,7 +68,7 @@ actor CompactBlockProcessor {
67
68
  let rewindDistance: Int
68
69
  let walletBirthdayProvider: () -> BlockHeight
69
70
  var walletBirthday: BlockHeight { walletBirthdayProvider() }
70
- let downloadBufferSize: Int = 10
71
+ let downloadBufferSize: Int = 100
71
72
  let network: ZcashNetwork
72
73
  let saplingActivation: BlockHeight
73
74
  let cacheDbURL: URL?
@@ -201,6 +202,8 @@ actor CompactBlockProcessor {
201
202
  deinit {
202
203
  syncTask?.cancel()
203
204
  syncTask = nil
205
+ mempoolDetectionTask?.cancel()
206
+ mempoolDetectionTask = nil
204
207
  }
205
208
 
206
209
  // swiftlint:disable:next cyclomatic_complexity
@@ -278,10 +281,15 @@ extension CompactBlockProcessor {
278
281
  syncTask = Task(priority: .userInitiated) {
279
282
  await run()
280
283
  }
284
+
285
+ mempoolDetectionTask = Task {
286
+ await watchMempool()
287
+ }
281
288
  }
282
289
 
283
290
  func stop() async {
284
291
  syncTask?.cancel()
292
+ mempoolDetectionTask?.cancel()
285
293
  self.backoffTimer?.invalidate()
286
294
  self.backoffTimer = nil
287
295
  await stopAllActions()
@@ -289,8 +297,8 @@ extension CompactBlockProcessor {
289
297
  serviceFailureRetryAttempts = 0
290
298
  }
291
299
 
292
- func latestHeight() async throws -> BlockHeight {
293
- try await blockDownloaderService.latestBlockHeight()
300
+ func latestHeight(mode: ServiceMode) async throws -> BlockHeight {
301
+ try await blockDownloaderService.latestBlockHeight(mode: mode)
294
302
  }
295
303
 
296
304
  func consensusBranchIdFor(_ height: Int32) -> Int32? {
@@ -367,6 +375,55 @@ private extension CompactBlockProcessor {
367
375
  }
368
376
  }
369
377
 
378
+ // MARK: - Mempool Detection
379
+
380
+ extension CompactBlockProcessor {
381
+ func watchMempool() async {
382
+ while !Task.isCancelled {
383
+ do {
384
+ try await consumeMempoolStream()
385
+
386
+ try await Task.sleep(nanoseconds: 500_000_000)
387
+ } catch {
388
+ // Connection hammering prevention, wait 30s in case stream failed
389
+ try? await Task.sleep(nanoseconds: 30_000_000_000)
390
+ }
391
+ }
392
+ }
393
+
394
+ func consumeMempoolStream() async throws {
395
+ let stream = try service.getMempoolStream()
396
+
397
+ do {
398
+ for try await rawTransaction in stream {
399
+ let mempoolTransactions = try await resolveMempools(rawTransaction: rawTransaction)
400
+
401
+ if !mempoolTransactions.isEmpty {
402
+ let height = BlockHeight(rawTransaction.height)
403
+ await send(event: .foundTransactions(mempoolTransactions, .init(uncheckedBounds: (lower: height, upper: height))))
404
+ }
405
+ }
406
+ } catch { }
407
+ }
408
+
409
+ @DBActor
410
+ func resolveMempools(rawTransaction: RawTransaction) async throws -> [ZcashTransaction.Overview] {
411
+ let minedHeight = (rawTransaction.height == 0 || rawTransaction.height > UInt32.max)
412
+ ? nil : UInt32(rawTransaction.height)
413
+
414
+ let txIdData = try await rustBackend.decryptAndStoreTransaction(
415
+ txBytes: rawTransaction.data.bytes,
416
+ minedHeight: minedHeight
417
+ )
418
+
419
+ if let transaction = try? await transactionRepository.find(rawID: txIdData) {
420
+ return [transaction]
421
+ }
422
+
423
+ return []
424
+ }
425
+ }
426
+
370
427
  // MARK: - Wipe
371
428
 
372
429
  extension CompactBlockProcessor {
@@ -374,6 +431,8 @@ extension CompactBlockProcessor {
374
431
  logger.debug("Starting wipe")
375
432
  if await isIdle() {
376
433
  logger.debug("Sync doesn't run. Executing wipe.")
434
+ self.backoffTimer?.invalidate()
435
+ self.backoffTimer = nil
377
436
  try await doWipe(context: context)
378
437
  } else {
379
438
  logger.debug("Stopping sync because of wipe")
@@ -483,10 +542,10 @@ extension CompactBlockProcessor {
483
542
  case handledReorg(_ reorgHeight: BlockHeight, _ rewindHeight: BlockHeight)
484
543
 
485
544
  /// Event sent when progress of some specific action happened.
486
- case syncProgress(Float)
545
+ case syncProgress(Float, Bool)
487
546
 
488
547
  /// Event sent when progress of the sync process changes.
489
- case progressUpdated(Float)
548
+ case progressUpdated(Float, Bool)
490
549
 
491
550
  /// Event sent when the CompactBlockProcessor fetched utxos from lightwalletd attempted to store them.
492
551
  case storedUTXOs((inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity]))
@@ -569,7 +628,9 @@ extension CompactBlockProcessor {
569
628
  await self?.send(event: event)
570
629
  if let progressChanged = await self?.compactBlockProgress.hasProgressUpdated(event), progressChanged {
571
630
  if let progress = await self?.compactBlockProgress.progress {
572
- await self?.send(event: .progressUpdated(progress))
631
+ await self?.send(
632
+ event: .progressUpdated(progress, self?.compactBlockProgress.areFundsSpendable ?? false)
633
+ )
573
634
  }
574
635
  }
575
636
  }
@@ -713,7 +774,7 @@ extension CompactBlockProcessor {
713
774
  let lastScannedHeight = await latestBlocksDataProvider.maxScannedHeight
714
775
  // Some actions may not run. For example there are no transactions to enhance and therefore there is no enhance progress. And in
715
776
  // cases like this computation of final progress won't work properly. So let's fake 100% progress at the end of the sync process.
716
- await send(event: .progressUpdated(1))
777
+ await send(event: .progressUpdated(1, false))
717
778
  await send(event: .finished(lastScannedHeight))
718
779
  await context.update(state: .finished)
719
780
 
@@ -776,7 +837,7 @@ extension CompactBlockProcessor {
776
837
  guard let self else { return }
777
838
  if await self.isIdle() {
778
839
  if await self.canStartSync() {
779
- self.logger.debug(
840
+ await self.logger.debug(
780
841
  """
781
842
  Timer triggered: Starting compact Block processor!.
782
843
  Processor State: \(await self.context.state)
@@ -837,16 +898,20 @@ extension CompactBlockProcessor {
837
898
  }
838
899
 
839
900
  extension CompactBlockProcessor {
840
- func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
841
- try await rustBackend.getCurrentAddress(account: Int32(accountIndex))
901
+ func getUnifiedAddress(accountUUID: AccountUUID) async throws -> UnifiedAddress {
902
+ try await rustBackend.getCurrentAddress(accountUUID: accountUUID)
842
903
  }
843
904
 
844
- func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress {
845
- try await getUnifiedAddress(accountIndex: accountIndex).saplingReceiver()
905
+ func getSaplingAddress(accountUUID: AccountUUID) async throws -> SaplingAddress {
906
+ try await getUnifiedAddress(accountUUID: accountUUID).saplingReceiver()
846
907
  }
847
908
 
848
- func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
849
- try await getUnifiedAddress(accountIndex: accountIndex).transparentReceiver()
909
+ func getTransparentAddress(accountUUID: AccountUUID) async throws -> TransparentAddress {
910
+ try await getUnifiedAddress(accountUUID: accountUUID).transparentReceiver()
911
+ }
912
+
913
+ func getCustomUnifiedAddress(accountUUID: AccountUUID, receivers: Set<ReceiverType>) async throws -> UnifiedAddress {
914
+ try await rustBackend.getNextAvailableAddress(accountUUID: accountUUID, receiverFlags: receivers.toFlags())
850
915
  }
851
916
  }
852
917
 
@@ -854,9 +919,11 @@ extension CompactBlockProcessor {
854
919
  func refreshUTXOs(tAddress: TransparentAddress, startHeight: BlockHeight) async throws -> RefreshedUTXOs {
855
920
  let dataDb = self.config.dataDb
856
921
 
857
- let stream: AsyncThrowingStream<UnspentTransactionOutputEntity, Error> = blockDownloaderService.fetchUnspentTransactionOutputs(
922
+ // ServiceMode to resolve
923
+ let stream: AsyncThrowingStream<UnspentTransactionOutputEntity, Error> = try blockDownloaderService.fetchUnspentTransactionOutputs(
858
924
  tAddress: tAddress.stringEncoded,
859
- startHeight: startHeight
925
+ startHeight: startHeight,
926
+ mode: .direct
860
927
  )
861
928
  var utxos: [UnspentTransactionOutputEntity] = []
862
929
 
@@ -135,7 +135,8 @@ actor BlockDownloaderImpl {
135
135
  logger.debug("Creating new stream for range \(streamRange.lowerBound)...\(streamRange.upperBound)")
136
136
 
137
137
  downloadStreamCreatedAtRange = streamRange
138
- let stream = service.blockStream(startHeight: streamRange.lowerBound, endHeight: streamRange.upperBound)
138
+ // ServiceMode to resolve
139
+ let stream = try service.blockStream(startHeight: streamRange.lowerBound, endHeight: streamRange.upperBound, mode: .direct)
139
140
  downloadStream = BlockDownloaderStream(stream: stream)
140
141
  self.downloadStream = downloadStream
141
142
  }
@@ -182,7 +183,8 @@ actor BlockDownloaderImpl {
182
183
 
183
184
  private func compactBlocksDownloadStream(startHeight: BlockHeight, targetHeight: BlockHeight) async throws -> BlockDownloaderStream {
184
185
  try Task.checkCancellation()
185
- let stream = service.blockStream(startHeight: startHeight, endHeight: targetHeight)
186
+ // ServiceMode to resolve
187
+ let stream = try service.blockStream(startHeight: startHeight, endHeight: targetHeight, mode: .direct)
186
188
  return BlockDownloaderStream(stream: stream)
187
189
  }
188
190
 
@@ -21,7 +21,7 @@ protocol BlockDownloaderService {
21
21
  /**
22
22
  Downloads and stores the given block range.
23
23
  */
24
- func downloadBlockRange(_ heightRange: CompactBlockRange) async throws
24
+ func downloadBlockRange(_ heightRange: CompactBlockRange, mode: ServiceMode) async throws
25
25
 
26
26
  /**
27
27
  Restore the download progress up to the given height.
@@ -37,19 +37,19 @@ protocol BlockDownloaderService {
37
37
  /**
38
38
  Returns the latest block height
39
39
  */
40
- func latestBlockHeight() async throws -> BlockHeight
40
+ func latestBlockHeight(mode: ServiceMode) async throws -> BlockHeight
41
41
 
42
42
  /**
43
43
  Gets the transaction for the Id given
44
44
  - Parameter txId: Data representing the transaction Id
45
45
  */
46
- func fetchTransaction(txId: Data) async throws -> (tx: ZcashTransaction.Fetched?, status: TransactionStatus)
46
+ func fetchTransaction(txId: Data, mode: ServiceMode) async throws -> (tx: ZcashTransaction.Fetched?, status: TransactionStatus)
47
47
 
48
- func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
48
+ func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight, mode: ServiceMode) throws -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
49
49
 
50
- func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
50
+ func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight, mode: ServiceMode) throws -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
51
51
 
52
- func closeConnection()
52
+ func closeConnections()
53
53
  }
54
54
 
55
55
  /**
@@ -71,27 +71,30 @@ class BlockDownloaderServiceImpl {
71
71
  }
72
72
 
73
73
  extension BlockDownloaderServiceImpl: BlockDownloaderService {
74
- func closeConnection() {
75
- lightwalletService.closeConnection()
74
+ func closeConnections() {
75
+ Task {
76
+ await lightwalletService.closeConnections()
77
+ }
76
78
  }
77
79
 
78
80
  func fetchUnspentTransactionOutputs(
79
81
  tAddresses: [String],
80
- startHeight: BlockHeight
81
- ) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
82
- lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight)
82
+ startHeight: BlockHeight,
83
+ mode: ServiceMode
84
+ ) throws -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
85
+ try lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight, mode: mode)
83
86
  }
84
87
 
85
- func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
86
- lightwalletService.fetchUTXOs(for: tAddress, height: startHeight)
88
+ func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight, mode: ServiceMode) throws -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
89
+ try lightwalletService.fetchUTXOs(for: tAddress, height: startHeight, mode: mode)
87
90
  }
88
91
 
89
- func latestBlockHeight() async throws -> BlockHeight {
90
- try await lightwalletService.latestBlockHeight()
92
+ func latestBlockHeight(mode: ServiceMode) async throws -> BlockHeight {
93
+ try await lightwalletService.latestBlockHeight(mode: mode)
91
94
  }
92
95
 
93
- func downloadBlockRange( _ heightRange: CompactBlockRange) async throws {
94
- let stream: AsyncThrowingStream<ZcashCompactBlock, Error> = lightwalletService.blockRange(heightRange)
96
+ func downloadBlockRange( _ heightRange: CompactBlockRange, mode: ServiceMode) async throws {
97
+ let stream: AsyncThrowingStream<ZcashCompactBlock, Error> = try lightwalletService.blockRange(heightRange, mode: mode)
95
98
  do {
96
99
  var compactBlocks: [ZcashCompactBlock] = []
97
100
  for try await compactBlock in stream {
@@ -111,7 +114,7 @@ extension BlockDownloaderServiceImpl: BlockDownloaderService {
111
114
  try await self.storage.latestHeight()
112
115
  }
113
116
 
114
- func fetchTransaction(txId: Data) async throws -> (tx: ZcashTransaction.Fetched?, status: TransactionStatus) {
115
- try await lightwalletService.fetchTransaction(txId: txId)
117
+ func fetchTransaction(txId: Data, mode: ServiceMode) async throws -> (tx: ZcashTransaction.Fetched?, status: TransactionStatus) {
118
+ try await lightwalletService.fetchTransaction(txId: txId, mode: mode)
116
119
  }
117
120
  }
@@ -62,17 +62,16 @@ struct BlockEnhancerImpl {
62
62
  let metrics: SDKMetrics
63
63
  let service: LightWalletService
64
64
  let logger: Logger
65
+ let sdkFlags: SDKFlags
65
66
  }
66
67
 
67
68
  extension BlockEnhancerImpl: BlockEnhancer {
69
+ // swiftlint:disable:next cyclomatic_complexity
68
70
  func enhance(at range: CompactBlockRange, didEnhance: @escaping (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]? {
69
71
  try Task.checkCancellation()
70
72
 
71
73
  logger.debug("Started Enhancing range: \(range)")
72
74
 
73
- var retries = 0
74
- let maxRetries = 5
75
-
76
75
  // fetch transactions
77
76
  do {
78
77
  let transactionDataRequests = try await rustBackend.transactionDataRequests()
@@ -86,49 +85,84 @@ extension BlockEnhancerImpl: BlockEnhancer {
86
85
  for index in 0 ..< transactionDataRequests.count {
87
86
  let transactionDataRequest = transactionDataRequests[index]
88
87
  var retry = true
88
+ var retries = 0
89
+ let maxRetries = 5
89
90
 
90
91
  while retry && retries < maxRetries {
91
92
  try Task.checkCancellation()
92
93
  do {
93
94
  switch transactionDataRequest {
94
95
  case .getStatus(let txId):
95
- let response = try await blockDownloaderService.fetchTransaction(txId: txId.data)
96
+ let response = try await blockDownloaderService.fetchTransaction(
97
+ txId: txId.data,
98
+ mode: await sdkFlags.ifTor(ServiceMode.txIdGroup(prefix: "fetch", txId: txId.data))
99
+ )
96
100
  retry = false
97
101
 
98
- if let fetchedTransaction = response.tx {
102
+ if response.status == .txidNotRecognized {
103
+ try await rustBackend.setTransactionStatus(txId: txId.data, status: response.status)
104
+ } else if let fetchedTransaction = response.tx {
99
105
  try await rustBackend.setTransactionStatus(txId: fetchedTransaction.rawID, status: response.status)
100
106
  }
101
107
 
102
108
  case .enhancement(let txId):
103
- let response = try await blockDownloaderService.fetchTransaction(txId: txId.data)
109
+ let response = try await blockDownloaderService.fetchTransaction(
110
+ txId: txId.data,
111
+ mode: await sdkFlags.ifTor(ServiceMode.txIdGroup(prefix: "fetch", txId: txId.data))
112
+ )
104
113
  retry = false
105
114
 
106
115
  if response.status == .txidNotRecognized {
107
116
  try await rustBackend.setTransactionStatus(txId: txId.data, status: .txidNotRecognized)
108
117
  } else if let fetchedTransaction = response.tx {
109
- try await rustBackend.decryptAndStoreTransaction(
118
+ _ = try await rustBackend.decryptAndStoreTransaction(
110
119
  txBytes: fetchedTransaction.raw.bytes,
111
120
  minedHeight: fetchedTransaction.minedHeight
112
121
  )
113
122
  }
114
123
 
115
- case .spendsFromAddress(let sfa):
116
- guard let blockRangeEnd = sfa.blockRangeEnd else {
117
- logger.error("spendsFromAddress \(sfa) is missing blockRangeEnd, ignoring the request.")
124
+ case .transactionsInvolvingAddress(let tia):
125
+ // TODO: [#1554] Remove this guard once lightwalletd servers support open-ended ranges.
126
+ guard tia.blockRangeEnd != nil else {
127
+ logger.error("transactionsInvolvingAddress \(tia) is missing blockRangeEnd, ignoring the request.")
128
+ retry = false
118
129
  continue
119
130
  }
120
-
131
+
132
+ // TODO: [#1551] Support this.
133
+ if tia.requestAt != nil {
134
+ logger.error("transactionsInvolvingAddress \(tia) has requestAt set, ignoring the unsupported request.")
135
+ retry = false
136
+ continue
137
+ }
138
+
139
+ // TODO: [#1552] Support the OutputStatusFilter
140
+ if tia.outputStatusFilter == .unspent {
141
+ retry = false
142
+ continue
143
+ }
144
+
121
145
  var filter = TransparentAddressBlockFilter()
122
- filter.address = sfa.address
123
- filter.range = BlockRange(startHeight: Int(sfa.blockRangeStart), endHeight: Int(blockRangeEnd - 1))
146
+ filter.address = tia.address
147
+ filter.range = if let blockRangeEnd = tia.blockRangeEnd {
148
+ BlockRange(startHeight: Int(tia.blockRangeStart), endHeight: Int(blockRangeEnd - 1))
149
+ } else {
150
+ BlockRange(startHeight: Int(tia.blockRangeStart))
151
+ }
124
152
 
125
- let stream = service.getTaddressTxids(filter)
153
+ // ServiceMode to resolve
154
+ let stream = try service.getTaddressTxids(filter, mode: .direct)
126
155
 
127
156
  for try await rawTransaction in stream {
128
- let minedHeight = (rawTransaction.height == 0 || rawTransaction.height > UInt32.max)
157
+ let minedHeight = (rawTransaction.height == 0 || rawTransaction.height > UInt32.max)
129
158
  ? nil : UInt32(rawTransaction.height)
130
159
 
131
- try await rustBackend.decryptAndStoreTransaction(
160
+ // Ignore transactions that don't match the status filter.
161
+ if (tia.txStatusFilter == .mined && minedHeight == nil) || (tia.txStatusFilter == .mempool && minedHeight != nil) {
162
+ continue
163
+ }
164
+
165
+ _ = try await rustBackend.decryptAndStoreTransaction(
132
166
  txBytes: rawTransaction.data.bytes,
133
167
  minedHeight: minedHeight
134
168
  )
@@ -138,9 +172,6 @@ extension BlockEnhancerImpl: BlockEnhancer {
138
172
  } catch {
139
173
  retries += 1
140
174
  logger.error("could not enhance transactionDataRequest \(transactionDataRequest) - Error: \(error)")
141
- if retries > maxRetries {
142
- throw error
143
- }
144
175
  }
145
176
  }
146
177
  }
@@ -40,13 +40,15 @@ extension UTXOFetcherImpl: UTXOFetcher {
40
40
 
41
41
  var tAddresses: [TransparentAddress] = []
42
42
  for account in accounts {
43
- tAddresses += try await rustBackend.listTransparentReceivers(account: Int32(account))
43
+ tAddresses += try await rustBackend.listTransparentReceivers(accountUUID: account.id)
44
44
  }
45
45
 
46
46
  var utxos: [UnspentTransactionOutputEntity] = []
47
- let stream: AsyncThrowingStream<UnspentTransactionOutputEntity, Error> = blockDownloaderService.fetchUnspentTransactionOutputs(
47
+ // ServiceMode to resolve
48
+ let stream: AsyncThrowingStream<UnspentTransactionOutputEntity, Error> = try blockDownloaderService.fetchUnspentTransactionOutputs(
48
49
  tAddresses: tAddresses.map { $0.stringEncoded },
49
- startHeight: await config.walletBirthdayProvider()
50
+ startHeight: BlockHeight(0),
51
+ mode: .direct
50
52
  )
51
53
 
52
54
  do {
@@ -28,13 +28,30 @@ extension SaplingParametersHandlerImpl: SaplingParametersHandler {
28
28
  try Task.checkCancellation()
29
29
 
30
30
  do {
31
- let totalSaplingBalance =
32
- try await rustBackend.getWalletSummary()?.accountBalances[0]?.saplingBalance.total().amount
33
- ?? 0
34
- let totalTransparentBalance = try await rustBackend.getTransparentBalance(account: Int32(0))
31
+ let accounts = try await rustBackend.listAccounts()
35
32
 
33
+ var totalSaplingBalanceTrigger = false
34
+ var totalTransparentBalanceTrigger = false
35
+ let accountBalances = try await rustBackend.getWalletSummary()?.accountBalances
36
+
37
+ for account in accounts {
38
+ let totalSaplingBalance = accountBalances?[account.id]?.saplingBalance.total().amount ?? 0
39
+
40
+ if totalSaplingBalance > 0 {
41
+ totalSaplingBalanceTrigger = true
42
+ break
43
+ }
44
+
45
+ let totalTransparentBalance = try await rustBackend.getTransparentBalance(accountUUID: account.id)
46
+
47
+ if totalTransparentBalance > 0 {
48
+ totalTransparentBalanceTrigger = true
49
+ break
50
+ }
51
+ }
52
+
36
53
  // Download Sapling parameters only if sapling funds are detected.
37
- guard totalSaplingBalance > 0 || totalTransparentBalance > 0 else { return }
54
+ guard totalSaplingBalanceTrigger || totalTransparentBalanceTrigger else { return }
38
55
  } catch {
39
56
  // if sapling balance can't be detected of we fail to obtain the balance
40
57
  // for some reason we shall not proceed to download the parameters and
@@ -57,7 +57,8 @@ extension BlockScannerImpl: BlockScanner {
57
57
  let scanSummary: ScanSummary
58
58
  let scanStartTime = Date()
59
59
  do {
60
- let fromState = try await service.getTreeState(BlockID(height: startHeight - 1))
60
+ // Directly correlated with `BlockDownloader` ranges.
61
+ let fromState = try await service.getTreeState(BlockID(height: startHeight - 1), mode: .direct)
61
62
 
62
63
  scanSummary = try await self.rustBackend.scanBlocks(fromHeight: Int32(startHeight), fromState: fromState, limit: batchSize)
63
64
  } catch {
@@ -11,14 +11,16 @@ final actor CompactBlockProgress {
11
11
  static let zero = CompactBlockProgress()
12
12
 
13
13
  var progress: Float = 0.0
14
+ var areFundsSpendable = false
14
15
 
15
16
  func hasProgressUpdated(_ event: CompactBlockProcessor.Event) -> Bool {
16
- guard case .syncProgress(let update) = event else {
17
+ guard case let .syncProgress(progress, areFundsSpendable) = event else {
17
18
  return false
18
19
  }
19
20
 
20
- progress = update
21
-
21
+ self.progress = progress
22
+ self.areFundsSpendable = areFundsSpendable
23
+
22
24
  return true
23
25
  }
24
26
  }
@@ -30,4 +30,92 @@ struct BundleCheckpointSource: CheckpointSource {
30
30
  checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
31
31
  ) ?? saplingActivation
32
32
  }
33
+
34
+ // swiftlint:disable:next cyclomatic_complexity
35
+ func estimateBirthdayHeight(for date: Date) -> BlockHeight {
36
+ // the average time between 2500 blocks during last 10 checkpoints (estimated March 31, 2025) is 52.33 hours for mainnet
37
+ // the average time between 10,000 blocks during last 10 checkpoints (estimated March 31, 2025) is 134.93 hours for testnet
38
+ let avgIntervalTime: TimeInterval = network == .mainnet ? 52.33 : 134.93
39
+ let blockInterval: Double = network == .mainnet ? 2500 : 10_000
40
+ let saplingActivationHeight = network == .mainnet
41
+ ? ZcashMainnet().constants.saplingActivationHeight
42
+ : ZcashTestnet().constants.saplingActivationHeight
43
+
44
+ let latestCheckpoint = latestKnownCheckpoint()
45
+ let latestCheckpointTime = TimeInterval(latestCheckpoint.time)
46
+
47
+ // above latest checkpoint, return it
48
+ guard date.timeIntervalSince1970 < latestCheckpointTime else {
49
+ return latestCheckpoint.height
50
+ }
51
+
52
+ // Phase 1, estimate possible height
53
+ let nowTimeIntervalSince1970 = Date().timeIntervalSince1970
54
+ let timeDiff = (nowTimeIntervalSince1970 - date.timeIntervalSince1970) - (nowTimeIntervalSince1970 - latestCheckpointTime)
55
+ let blockDiff = ((timeDiff / 3600) / avgIntervalTime) * blockInterval
56
+
57
+ var heightToLookAround = Double(Int(latestCheckpoint.height - Int(blockDiff)) / Int(blockInterval)) * blockInterval
58
+
59
+ // bellow sapling activation height
60
+ guard Int(heightToLookAround) > saplingActivationHeight else {
61
+ return saplingActivationHeight
62
+ }
63
+
64
+ // Phase 2, load checkpoint and evaluate against given date
65
+ guard let loadedCheckpoint = Checkpoint.birthday(
66
+ with: BlockHeight(heightToLookAround),
67
+ checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
68
+ ) else {
69
+ return saplingActivationHeight
70
+ }
71
+
72
+ // loaded checkpoint is exactly the one
73
+ var hoursApart = (TimeInterval(loadedCheckpoint.time) - date.timeIntervalSince1970) / 3600
74
+ if hoursApart < 0 && abs(hoursApart) < avgIntervalTime {
75
+ return loadedCheckpoint.height
76
+ }
77
+
78
+ if hoursApart < 0 {
79
+ // loaded checkpoint is lower, increase until reached the one
80
+ var closestHeight = loadedCheckpoint.height
81
+ while abs(hoursApart) > avgIntervalTime {
82
+ heightToLookAround += blockInterval
83
+
84
+ if let loadedCheckpoint = Checkpoint.birthday(
85
+ with: BlockHeight(heightToLookAround),
86
+ checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
87
+ ) {
88
+ hoursApart = (TimeInterval(loadedCheckpoint.time) - date.timeIntervalSince1970) / 3600
89
+ if hoursApart < 0 && abs(hoursApart) < avgIntervalTime {
90
+ return loadedCheckpoint.height
91
+ } else if hoursApart >= 0 {
92
+ return closestHeight
93
+ }
94
+
95
+ closestHeight = loadedCheckpoint.height
96
+ } else {
97
+ return saplingActivationHeight
98
+ }
99
+ }
100
+ } else {
101
+ // loaded checkpoint is higher, descrease until reached the one
102
+ while hoursApart > 0 {
103
+ heightToLookAround -= blockInterval
104
+
105
+ if let loadedCheckpoint = Checkpoint.birthday(
106
+ with: BlockHeight(heightToLookAround),
107
+ checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
108
+ ) {
109
+ hoursApart = (TimeInterval(loadedCheckpoint.time) - date.timeIntervalSince1970) / 3600
110
+ if hoursApart < 0 {
111
+ return loadedCheckpoint.height
112
+ }
113
+ } else {
114
+ return saplingActivationHeight
115
+ }
116
+ }
117
+ }
118
+
119
+ return saplingActivationHeight
120
+ }
33
121
  }