react-native-zcash 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +6 -3
- package/android/build.gradle +5 -4
- package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2240000.json +8 -0
- package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2250000.json +8 -0
- package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +94 -121
- package/ios/RNZcash.m +1 -12
- package/ios/RNZcash.swift +119 -152
- package/ios/ZCashLightClientKit/Block/Actions/Action.swift +98 -0
- package/ios/ZCashLightClientKit/Block/Actions/ClearAlreadyScannedBlocksAction.swift +35 -0
- package/ios/ZCashLightClientKit/Block/Actions/ClearCacheAction.swift +30 -0
- package/ios/ZCashLightClientKit/Block/Actions/DownloadAction.swift +67 -0
- package/ios/ZCashLightClientKit/Block/Actions/EnhanceAction.swift +97 -0
- package/ios/ZCashLightClientKit/Block/Actions/FetchUTXOsAction.swift +33 -0
- package/ios/ZCashLightClientKit/Block/Actions/MigrateLegacyCacheDBAction.swift +70 -0
- package/ios/ZCashLightClientKit/Block/Actions/ProcessSuggestedScanRangesAction.swift +59 -0
- package/ios/ZCashLightClientKit/Block/Actions/RewindAction.swift +48 -0
- package/ios/ZCashLightClientKit/Block/Actions/SaplingParamsAction.swift +33 -0
- package/ios/ZCashLightClientKit/Block/Actions/ScanAction.swift +95 -0
- package/ios/ZCashLightClientKit/Block/Actions/UpdateChainTipAction.swift +55 -0
- package/ios/ZCashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +58 -0
- package/ios/ZCashLightClientKit/Block/Actions/ValidateServerAction.swift +60 -0
- package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +421 -937
- package/ios/ZCashLightClientKit/Block/Download/BlockDownloader.swift +31 -17
- package/ios/ZCashLightClientKit/Block/Download/BlockDownloaderService.swift +2 -2
- package/ios/ZCashLightClientKit/Block/Enhance/BlockEnhancer.swift +46 -15
- package/ios/ZCashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +4 -15
- package/ios/ZCashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift +4 -4
- package/ios/ZCashLightClientKit/Block/Scan/BlockScanner.swift +10 -35
- package/ios/ZCashLightClientKit/Block/Utils/CompactBlockProgress.swift +24 -0
- package/ios/ZCashLightClientKit/Block/Utils/SyncControlData.swift +25 -0
- package/ios/ZCashLightClientKit/ClosureSynchronizer.swift +1 -2
- package/ios/ZCashLightClientKit/CombineSynchronizer.swift +2 -5
- package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +7 -25
- package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +40 -42
- package/ios/ZCashLightClientKit/DAO/UnspentTransactionOutputDao.swift +13 -4
- package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +9 -0
- package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +7 -10
- package/ios/ZCashLightClientKit/Error/Sourcery/generateErrorCode.sh +1 -1
- package/ios/ZCashLightClientKit/Error/ZcashError.swift +121 -12
- package/ios/ZCashLightClientKit/Error/ZcashErrorCode.swift +43 -5
- package/ios/ZCashLightClientKit/Error/ZcashErrorCodeDefinition.swift +72 -6
- package/ios/ZCashLightClientKit/Extensions/Bool+ToData.swift +15 -0
- package/ios/ZCashLightClientKit/Extensions/Data+ToOtherTypes.swift +18 -0
- package/ios/ZCashLightClientKit/Extensions/Int+ToData.swift +15 -0
- package/ios/ZCashLightClientKit/Initializer.swift +47 -26
- package/ios/ZCashLightClientKit/Metrics/SDKMetrics.swift +0 -12
- package/ios/ZCashLightClientKit/Model/Checkpoint.swift +12 -0
- package/ios/ZCashLightClientKit/Model/ScanProgress.swift +29 -0
- package/ios/ZCashLightClientKit/Model/ScanRange.swift +31 -0
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/LightWalletGRPCService.swift +15 -0
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift +150 -46
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto +30 -16
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto +32 -6
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift +259 -22
- package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift +193 -7
- package/ios/ZCashLightClientKit/Modules/Service/LightWalletService.swift +8 -0
- package/ios/ZCashLightClientKit/Providers/LatestBlocksDataProvider.swift +18 -28
- package/ios/ZCashLightClientKit/Repository/CompactBlockRepository.swift +1 -1
- package/ios/ZCashLightClientKit/Repository/TransactionRepository.swift +2 -6
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2092500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2095000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2097500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2102500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2105000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2107500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2112500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2115000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2117500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2122500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2125000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2127500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2132500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2135000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2137500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2142500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2145000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2147500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2152500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2155000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2157500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2162500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2165000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2167500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2172500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2175000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2177500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2182500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2185000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2187500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2192500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2195000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2197500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2202500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2205000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2207500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2212500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2215000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2217500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2222500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2225000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2227500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2230000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2232500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2235000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2237500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2240000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2242500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2245000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2247500.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2250000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2350000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2360000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2370000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2380000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2390000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2400000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2410000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2420000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2430000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2440000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2450000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2460000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2470000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2480000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2490000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2500000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2510000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2520000.json +8 -0
- package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2530000.json +8 -0
- package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +293 -158
- package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +58 -64
- package/ios/ZCashLightClientKit/Rust/zcashlc.h +618 -512
- package/ios/ZCashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +2 -8
- package/ios/ZCashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +3 -15
- package/ios/ZCashLightClientKit/Synchronizer/Dependencies.swift +11 -30
- package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +41 -50
- package/ios/ZCashLightClientKit/Synchronizer.swift +51 -65
- package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +2 -2
- package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +7 -7
- package/ios/ZCashLightClientKit/Utils/OSLogger.swift +3 -3
- package/ios/ZCashLightClientKit/Utils/ZcashFileManager.swift +16 -0
- package/ios/libzcashlc.xcframework/Info.plist +9 -5
- package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
- package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
- package/lib/rnzcash.rn.js +8 -30
- package/lib/rnzcash.rn.js.map +1 -1
- package/lib/src/react-native.d.ts +2 -4
- package/lib/src/types.d.ts +14 -14
- package/package.json +1 -1
- package/src/react-native.ts +11 -20
- package/src/types.ts +20 -23
- package/ios/ZCashLightClientKit/Block/Utils/InternalSyncProgress.swift +0 -200
- package/ios/ZCashLightClientKit/Block/Validate/BlockValidator.swift +0 -51
- package/ios/ZCashLightClientKit/DAO/BlockDao.swift +0 -112
- package/ios/ZCashLightClientKit/Entity/BlockProgress.swift +0 -24
package/ios/RNZcash.swift
CHANGED
|
@@ -8,17 +8,21 @@ var SynchronizerMap = [String: WalletSynchronizer]()
|
|
|
8
8
|
struct ConfirmedTx {
|
|
9
9
|
var minedHeight: Int
|
|
10
10
|
var toAddress: String?
|
|
11
|
+
var raw: String?
|
|
11
12
|
var rawTransactionId: String
|
|
12
13
|
var blockTimeInSeconds: Int
|
|
13
14
|
var value: String
|
|
15
|
+
var fee: String?
|
|
14
16
|
var memos: Array<String>?
|
|
15
17
|
var dictionary: [String: Any?] {
|
|
16
18
|
return [
|
|
17
19
|
"minedHeight": minedHeight,
|
|
18
20
|
"toAddress": toAddress,
|
|
21
|
+
"raw": raw,
|
|
19
22
|
"rawTransactionId": rawTransactionId,
|
|
20
23
|
"blockTimeInSeconds": blockTimeInSeconds,
|
|
21
24
|
"value": value,
|
|
25
|
+
"fee": fee,
|
|
22
26
|
"memos": memos ?? [],
|
|
23
27
|
]
|
|
24
28
|
}
|
|
@@ -42,16 +46,10 @@ struct TotalBalances {
|
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
struct ProcessorState {
|
|
45
|
-
var alias: String
|
|
46
|
-
var lastDownloadedHeight: Int
|
|
47
|
-
var lastScannedHeight: Int
|
|
48
49
|
var scanProgress: Int
|
|
49
50
|
var networkBlockHeight: Int
|
|
50
51
|
var dictionary: [String: Any] {
|
|
51
52
|
return [
|
|
52
|
-
"alias": alias,
|
|
53
|
-
"lastDownloadedHeight": lastDownloadedHeight,
|
|
54
|
-
"lastScannedHeight": lastScannedHeight,
|
|
55
53
|
"scanProgress": scanProgress,
|
|
56
54
|
"networkBlockHeight": networkBlockHeight,
|
|
57
55
|
]
|
|
@@ -83,7 +81,7 @@ class RNZcash: RCTEventEmitter {
|
|
|
83
81
|
// Synchronizer
|
|
84
82
|
@objc func initialize(
|
|
85
83
|
_ seed: String, _ birthdayHeight: Int, _ alias: String, _ networkName: String,
|
|
86
|
-
_ defaultHost: String, _ defaultPort: Int, resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
84
|
+
_ defaultHost: String, _ defaultPort: Int, _ newWallet: Bool, resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
87
85
|
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
88
86
|
) {
|
|
89
87
|
Task {
|
|
@@ -92,6 +90,7 @@ class RNZcash: RCTEventEmitter {
|
|
|
92
90
|
let initializer = Initializer(
|
|
93
91
|
cacheDbURL: try! cacheDbURLHelper(alias, network),
|
|
94
92
|
fsBlockDbRoot: try! fsBlockDbRootURLHelper(alias, network),
|
|
93
|
+
generalStorageURL: try! generalStorageURLHelper(alias, network),
|
|
95
94
|
dataDbURL: try! dataDbURLHelper(alias, network),
|
|
96
95
|
endpoint: endpoint,
|
|
97
96
|
network: network,
|
|
@@ -105,12 +104,12 @@ class RNZcash: RCTEventEmitter {
|
|
|
105
104
|
let wallet = try WalletSynchronizer(
|
|
106
105
|
alias: alias, initializer: initializer, emitter: sendToJs)
|
|
107
106
|
let seedBytes = try Mnemonic.deterministicSeedBytes(from: seed)
|
|
108
|
-
let
|
|
107
|
+
let initMode = newWallet ? WalletInitMode.newWallet : WalletInitMode.existingWallet
|
|
109
108
|
|
|
110
109
|
_ = try await wallet.synchronizer.prepare(
|
|
111
110
|
with: seedBytes,
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
walletBirthday: birthdayHeight,
|
|
112
|
+
for: initMode
|
|
114
113
|
)
|
|
115
114
|
try await wallet.synchronizer.start()
|
|
116
115
|
wallet.subscribe()
|
|
@@ -221,7 +220,7 @@ class RNZcash: RCTEventEmitter {
|
|
|
221
220
|
memo: sdkMemo
|
|
222
221
|
)
|
|
223
222
|
|
|
224
|
-
let tx: NSMutableDictionary = ["txId": broadcastTx.rawID.
|
|
223
|
+
let tx: NSMutableDictionary = ["txId": broadcastTx.rawID.toHexStringTxId()]
|
|
225
224
|
if broadcastTx.raw != nil {
|
|
226
225
|
tx["raw"] = broadcastTx.raw?.hexEncodedString()
|
|
227
226
|
}
|
|
@@ -235,97 +234,6 @@ class RNZcash: RCTEventEmitter {
|
|
|
235
234
|
}
|
|
236
235
|
}
|
|
237
236
|
|
|
238
|
-
@objc func getTransactions(
|
|
239
|
-
_ alias: String, _ first: Int, _ last: Int, resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
240
|
-
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
241
|
-
) {
|
|
242
|
-
Task {
|
|
243
|
-
if let wallet = SynchronizerMap[alias] {
|
|
244
|
-
if !wallet.fullySynced {
|
|
245
|
-
reject("GetTransactionsError", "Wallet is not synced", genericError)
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
var out: [NSDictionary] = []
|
|
250
|
-
do {
|
|
251
|
-
let txs = try await wallet.synchronizer.allTransactions()
|
|
252
|
-
let filterTxs = txs.filter {
|
|
253
|
-
$0.minedHeight != nil && $0.minedHeight! >= first && $0.minedHeight! <= last
|
|
254
|
-
&& $0.blockTime != nil
|
|
255
|
-
}
|
|
256
|
-
for tx in filterTxs {
|
|
257
|
-
var confTx = ConfirmedTx(
|
|
258
|
-
minedHeight: tx.minedHeight!,
|
|
259
|
-
rawTransactionId: (tx.rawID.toHexStringTxId()),
|
|
260
|
-
blockTimeInSeconds: Int(tx.blockTime!),
|
|
261
|
-
value: String(describing: abs(tx.value.amount))
|
|
262
|
-
)
|
|
263
|
-
if tx.isSentTransaction {
|
|
264
|
-
let recipients = await wallet.synchronizer.getRecipients(for: tx)
|
|
265
|
-
if recipients.count > 0 {
|
|
266
|
-
let addresses = recipients.compactMap {
|
|
267
|
-
if case let .address(address) = $0 {
|
|
268
|
-
return address
|
|
269
|
-
} else {
|
|
270
|
-
return nil
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if addresses.count > 0 {
|
|
274
|
-
confTx.toAddress = addresses.first!.stringEncoded
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if tx.memoCount > 0 {
|
|
279
|
-
let memos = (try? await wallet.synchronizer.getMemos(for: tx)) ?? []
|
|
280
|
-
let textMemos = memos.compactMap {
|
|
281
|
-
return $0.toString()
|
|
282
|
-
}
|
|
283
|
-
confTx.memos = textMemos
|
|
284
|
-
}
|
|
285
|
-
out.append(confTx.nsDictionary)
|
|
286
|
-
}
|
|
287
|
-
resolve(out)
|
|
288
|
-
} catch {
|
|
289
|
-
reject("GetTransactionsError", "Failed to get transactions", genericError)
|
|
290
|
-
}
|
|
291
|
-
} else {
|
|
292
|
-
reject("GetTransactionsError", "Wallet does not exist", genericError)
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
@objc func getBalance(
|
|
298
|
-
_ alias: String, resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
299
|
-
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
300
|
-
) {
|
|
301
|
-
Task {
|
|
302
|
-
if let wallet = SynchronizerMap[alias] {
|
|
303
|
-
do {
|
|
304
|
-
let totalShieldedBalance = try await wallet.synchronizer.getShieldedBalance()
|
|
305
|
-
let availableShieldedBalance = try await wallet.synchronizer.getShieldedVerifiedBalance()
|
|
306
|
-
|
|
307
|
-
let transparentWalletBalance = try await wallet.synchronizer.getTransparentBalance(
|
|
308
|
-
accountIndex: 0)
|
|
309
|
-
let totalTransparentBalance = transparentWalletBalance.total
|
|
310
|
-
let availableTransparentBalance = transparentWalletBalance.verified
|
|
311
|
-
|
|
312
|
-
let totalAvailable = availableShieldedBalance + availableTransparentBalance
|
|
313
|
-
let totalTotal = totalShieldedBalance + totalTransparentBalance
|
|
314
|
-
|
|
315
|
-
let balance = TotalBalances(
|
|
316
|
-
availableZatoshi: String(totalAvailable.amount), totalZatoshi: String(totalTotal.amount)
|
|
317
|
-
)
|
|
318
|
-
resolve(balance.nsDictionary)
|
|
319
|
-
return
|
|
320
|
-
} catch {
|
|
321
|
-
reject("GetShieldedBalanceError", "Error", error)
|
|
322
|
-
}
|
|
323
|
-
} else {
|
|
324
|
-
reject("GetShieldedBalanceError", "Wallet does not exist", genericError)
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
237
|
@objc func rescan(
|
|
330
238
|
_ alias: String, resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
331
239
|
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
@@ -343,6 +251,7 @@ class RNZcash: RCTEventEmitter {
|
|
|
343
251
|
wallet.initializeProcessorState()
|
|
344
252
|
wallet.cancellables.forEach { $0.cancel() }
|
|
345
253
|
wallet.subscribe()
|
|
254
|
+
try await wallet.synchronizer.start()
|
|
346
255
|
resolve(nil)
|
|
347
256
|
case .failure:
|
|
348
257
|
reject("RescanError", "Failed to rescan wallet", genericError)
|
|
@@ -444,7 +353,7 @@ class RNZcash: RCTEventEmitter {
|
|
|
444
353
|
}
|
|
445
354
|
|
|
446
355
|
override func supportedEvents() -> [String] {
|
|
447
|
-
return ["StatusEvent", "UpdateEvent"]
|
|
356
|
+
return ["BalanceEvent", "StatusEvent", "TransactionEvent", "UpdateEvent"]
|
|
448
357
|
}
|
|
449
358
|
}
|
|
450
359
|
|
|
@@ -457,6 +366,7 @@ class WalletSynchronizer: NSObject {
|
|
|
457
366
|
var restart: Bool
|
|
458
367
|
var processorState: ProcessorState
|
|
459
368
|
var cancellables: [AnyCancellable] = []
|
|
369
|
+
var balances: TotalBalances
|
|
460
370
|
|
|
461
371
|
init(alias: String, initializer: Initializer, emitter: @escaping (String, Any) -> Void) throws {
|
|
462
372
|
self.alias = alias
|
|
@@ -466,12 +376,10 @@ class WalletSynchronizer: NSObject {
|
|
|
466
376
|
self.fullySynced = false
|
|
467
377
|
self.restart = false
|
|
468
378
|
self.processorState = ProcessorState(
|
|
469
|
-
alias: self.alias,
|
|
470
|
-
lastDownloadedHeight: 0,
|
|
471
|
-
lastScannedHeight: 0,
|
|
472
379
|
scanProgress: 0,
|
|
473
380
|
networkBlockHeight: 0
|
|
474
381
|
)
|
|
382
|
+
self.balances = TotalBalances(availableZatoshi: "0", totalZatoshi: "0")
|
|
475
383
|
}
|
|
476
384
|
|
|
477
385
|
public func subscribe() {
|
|
@@ -479,10 +387,25 @@ class WalletSynchronizer: NSObject {
|
|
|
479
387
|
.throttle(for: .seconds(0.3), scheduler: DispatchQueue.main, latest: true)
|
|
480
388
|
.sink(receiveValue: { [weak self] state in self?.updateSyncStatus(event: state) })
|
|
481
389
|
.store(in: &cancellables)
|
|
390
|
+
self.synchronizer.stateStream
|
|
391
|
+
.sink(receiveValue: { [weak self] state in self?.updateProcessorState(event: state) })
|
|
392
|
+
.store(in: &cancellables)
|
|
393
|
+
self.synchronizer.eventStream
|
|
394
|
+
.sink { SynchronizerEvent in
|
|
395
|
+
switch SynchronizerEvent {
|
|
396
|
+
case .minedTransaction(let transaction):
|
|
397
|
+
self.emitTxs(transactions: [transaction])
|
|
398
|
+
case .foundTransactions(let transactions, _):
|
|
399
|
+
self.emitTxs(transactions: transactions)
|
|
400
|
+
default:
|
|
401
|
+
return
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
.store(in: &cancellables)
|
|
482
405
|
}
|
|
483
406
|
|
|
484
407
|
func updateSyncStatus(event: SynchronizerState) {
|
|
485
|
-
|
|
408
|
+
|
|
486
409
|
if !self.fullySynced {
|
|
487
410
|
switch event.internalSyncStatus {
|
|
488
411
|
case .syncing:
|
|
@@ -502,68 +425,104 @@ class WalletSynchronizer: NSObject {
|
|
|
502
425
|
let data: NSDictionary = ["alias": self.alias, "name": self.status]
|
|
503
426
|
emit("StatusEvent", data)
|
|
504
427
|
}
|
|
505
|
-
|
|
506
|
-
updateProcessorState(event: event)
|
|
507
428
|
}
|
|
508
429
|
|
|
509
430
|
func updateProcessorState(event: SynchronizerState) {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
let
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
self.processorState.lastDownloadedHeight = status.progressHeight
|
|
523
|
-
self.processorState.scanProgress = Int(floor(status.progress * 100))
|
|
524
|
-
self.processorState.lastScannedHeight = status.progressHeight
|
|
525
|
-
self.processorState.networkBlockHeight = status.targetHeight
|
|
526
|
-
default:
|
|
527
|
-
return
|
|
528
|
-
}
|
|
529
|
-
} else {
|
|
530
|
-
self.processorState.lastDownloadedHeight = self.synchronizer.latestState.latestScannedHeight
|
|
531
|
-
self.processorState.scanProgress = 100
|
|
532
|
-
self.processorState.lastScannedHeight = self.synchronizer.latestState.latestScannedHeight
|
|
533
|
-
self.processorState.networkBlockHeight = event.latestBlockHeight
|
|
431
|
+
var scanProgress = 0
|
|
432
|
+
|
|
433
|
+
switch event.internalSyncStatus {
|
|
434
|
+
case .syncing(let progress):
|
|
435
|
+
scanProgress = Int(floor(progress * 100))
|
|
436
|
+
case .synced:
|
|
437
|
+
scanProgress = 100
|
|
438
|
+
case .unprepared, .disconnected, .stopped:
|
|
439
|
+
scanProgress = 0
|
|
440
|
+
default:
|
|
441
|
+
return
|
|
534
442
|
}
|
|
535
443
|
|
|
536
|
-
if self.processorState.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
444
|
+
if (scanProgress == self.processorState.scanProgress && event.latestBlockHeight == self.processorState.networkBlockHeight) { return }
|
|
445
|
+
|
|
446
|
+
self.processorState = ProcessorState(scanProgress: scanProgress, networkBlockHeight: event.latestBlockHeight)
|
|
447
|
+
let data: NSDictionary = ["alias": self.alias, "scanProgress": self.processorState.scanProgress, "networkBlockHeight": self.processorState.networkBlockHeight]
|
|
448
|
+
emit("UpdateEvent", data)
|
|
449
|
+
updateBalanceState(event: event)
|
|
543
450
|
}
|
|
544
451
|
|
|
545
452
|
func initializeProcessorState() {
|
|
546
453
|
self.processorState = ProcessorState(
|
|
547
|
-
alias: self.alias,
|
|
548
|
-
lastDownloadedHeight: 0,
|
|
549
|
-
lastScannedHeight: 0,
|
|
550
454
|
scanProgress: 0,
|
|
551
455
|
networkBlockHeight: 0
|
|
552
456
|
)
|
|
457
|
+
self.balances = TotalBalances(availableZatoshi: "0", totalZatoshi: "0")
|
|
553
458
|
}
|
|
554
|
-
}
|
|
555
459
|
|
|
556
|
-
func
|
|
557
|
-
|
|
558
|
-
|
|
460
|
+
func updateBalanceState(event: SynchronizerState) {
|
|
461
|
+
let transparentBalance = event.transparentBalance
|
|
462
|
+
let shieldedBalance = event.shieldedBalance
|
|
463
|
+
|
|
464
|
+
let availableTransparentBalance = transparentBalance.verified
|
|
465
|
+
let totalTransparentBalance = transparentBalance.total
|
|
466
|
+
|
|
467
|
+
let availableShieldedBalance = shieldedBalance.verified
|
|
468
|
+
let totalShieldedBalance = shieldedBalance.total
|
|
469
|
+
|
|
470
|
+
let availableZatoshi = String((availableShieldedBalance + availableTransparentBalance).amount)
|
|
471
|
+
let totalZatoshi = String((totalShieldedBalance + totalTransparentBalance).amount)
|
|
472
|
+
|
|
473
|
+
if (availableZatoshi == self.balances.availableZatoshi && totalZatoshi == self.balances.totalZatoshi) { return }
|
|
559
474
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
chars.append(hexDigits[Int(byte % 16)])
|
|
475
|
+
self.balances = TotalBalances(availableZatoshi: availableZatoshi, totalZatoshi: totalZatoshi)
|
|
476
|
+
let data: NSDictionary = ["alias": self.alias, "availableZatoshi": self.balances.availableZatoshi, "totalZatoshi": self.balances.totalZatoshi]
|
|
477
|
+
emit("BalanceEvent", data)
|
|
564
478
|
}
|
|
565
479
|
|
|
566
|
-
|
|
480
|
+
func emitTxs(transactions: [ZcashTransaction.Overview]) {
|
|
481
|
+
Task {
|
|
482
|
+
var out: [NSDictionary] = []
|
|
483
|
+
for tx in transactions {
|
|
484
|
+
if (tx.isExpiredUmined ?? false) { continue }
|
|
485
|
+
var confTx = ConfirmedTx(
|
|
486
|
+
minedHeight: tx.minedHeight!,
|
|
487
|
+
rawTransactionId: (tx.rawID.toHexStringTxId()),
|
|
488
|
+
blockTimeInSeconds: Int(tx.blockTime!),
|
|
489
|
+
value: String(describing: abs(tx.value.amount))
|
|
490
|
+
)
|
|
491
|
+
if tx.raw != nil {
|
|
492
|
+
confTx.raw = tx.raw!.hexEncodedString()
|
|
493
|
+
}
|
|
494
|
+
if tx.fee != nil {
|
|
495
|
+
confTx.fee = String(describing: abs(tx.value.amount))
|
|
496
|
+
}
|
|
497
|
+
if tx.isSentTransaction {
|
|
498
|
+
let recipients = await self.synchronizer.getRecipients(for: tx)
|
|
499
|
+
if recipients.count > 0 {
|
|
500
|
+
let addresses = recipients.compactMap {
|
|
501
|
+
if case let .address(address) = $0 {
|
|
502
|
+
return address
|
|
503
|
+
} else {
|
|
504
|
+
return nil
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if addresses.count > 0 {
|
|
508
|
+
confTx.toAddress = addresses.first!.stringEncoded
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if tx.memoCount > 0 {
|
|
513
|
+
let memos = (try? await self.synchronizer.getMemos(for: tx)) ?? []
|
|
514
|
+
let textMemos = memos.compactMap {
|
|
515
|
+
return $0.toString()
|
|
516
|
+
}
|
|
517
|
+
confTx.memos = textMemos
|
|
518
|
+
}
|
|
519
|
+
out.append(confTx.nsDictionary)
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
let data: NSDictionary = ["alias": self.alias, "transactions": NSArray(array: out)]
|
|
523
|
+
emit("TransactionEvent", data)
|
|
524
|
+
}
|
|
525
|
+
}
|
|
567
526
|
}
|
|
568
527
|
|
|
569
528
|
// Local file helper funcs
|
|
@@ -603,3 +562,11 @@ func fsBlockDbRootURLHelper(_ alias: String, _ network: ZcashNetwork) throws ->
|
|
|
603
562
|
isDirectory: true
|
|
604
563
|
)
|
|
605
564
|
}
|
|
565
|
+
|
|
566
|
+
func generalStorageURLHelper(_ alias: String, _ network: ZcashNetwork) throws -> URL {
|
|
567
|
+
try documentsDirectoryHelper()
|
|
568
|
+
.appendingPathComponent(
|
|
569
|
+
network.constants.defaultDbNamePrefix + alias + "general_storage",
|
|
570
|
+
isDirectory: true
|
|
571
|
+
)
|
|
572
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Action.swift
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Created by Michal Fousek on 05.05.2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
protocol ActionContext {
|
|
11
|
+
var state: CBPState { get async }
|
|
12
|
+
var prevState: CBPState? { get async }
|
|
13
|
+
var syncControlData: SyncControlData { get async }
|
|
14
|
+
var requestedRewindHeight: BlockHeight? { get async }
|
|
15
|
+
var processedHeight: BlockHeight { get async }
|
|
16
|
+
var lastChainTipUpdateTime: TimeInterval { get async }
|
|
17
|
+
var lastScannedHeight: BlockHeight? { get async }
|
|
18
|
+
var lastEnhancedHeight: BlockHeight? { get async }
|
|
19
|
+
|
|
20
|
+
func update(state: CBPState) async
|
|
21
|
+
func update(syncControlData: SyncControlData) async
|
|
22
|
+
func update(processedHeight: BlockHeight) async
|
|
23
|
+
func update(lastChainTipUpdateTime: TimeInterval) async
|
|
24
|
+
func update(lastScannedHeight: BlockHeight) async
|
|
25
|
+
func update(lastDownloadedHeight: BlockHeight) async
|
|
26
|
+
func update(lastEnhancedHeight: BlockHeight?) async
|
|
27
|
+
func update(requestedRewindHeight: BlockHeight) async
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
actor ActionContextImpl: ActionContext {
|
|
31
|
+
var state: CBPState
|
|
32
|
+
var prevState: CBPState?
|
|
33
|
+
var syncControlData: SyncControlData
|
|
34
|
+
var requestedRewindHeight: BlockHeight?
|
|
35
|
+
/// Amount of blocks that have been processed so far
|
|
36
|
+
var processedHeight: BlockHeight = 0
|
|
37
|
+
/// Update chain tip must be called repeatadly, this value stores the previous update and help to decide when to call it again
|
|
38
|
+
var lastChainTipUpdateTime: TimeInterval = 0.0
|
|
39
|
+
var lastScannedHeight: BlockHeight?
|
|
40
|
+
var lastDownloadedHeight: BlockHeight?
|
|
41
|
+
var lastEnhancedHeight: BlockHeight?
|
|
42
|
+
|
|
43
|
+
init(state: CBPState) {
|
|
44
|
+
self.state = state
|
|
45
|
+
syncControlData = SyncControlData.empty
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func update(state: CBPState) async {
|
|
49
|
+
prevState = self.state
|
|
50
|
+
self.state = state
|
|
51
|
+
}
|
|
52
|
+
func update(syncControlData: SyncControlData) async { self.syncControlData = syncControlData }
|
|
53
|
+
func update(processedHeight: BlockHeight) async { self.processedHeight = processedHeight }
|
|
54
|
+
func update(lastChainTipUpdateTime: TimeInterval) async { self.lastChainTipUpdateTime = lastChainTipUpdateTime }
|
|
55
|
+
func update(lastScannedHeight: BlockHeight) async { self.lastScannedHeight = lastScannedHeight }
|
|
56
|
+
func update(lastDownloadedHeight: BlockHeight) async { self.lastDownloadedHeight = lastDownloadedHeight }
|
|
57
|
+
func update(lastEnhancedHeight: BlockHeight?) async { self.lastEnhancedHeight = lastEnhancedHeight }
|
|
58
|
+
func update(requestedRewindHeight: BlockHeight) async { self.requestedRewindHeight = requestedRewindHeight }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
enum CBPState: CaseIterable {
|
|
62
|
+
case idle
|
|
63
|
+
case migrateLegacyCacheDB
|
|
64
|
+
case validateServer
|
|
65
|
+
case updateSubtreeRoots
|
|
66
|
+
case updateChainTip
|
|
67
|
+
case processSuggestedScanRanges
|
|
68
|
+
case rewind
|
|
69
|
+
case download
|
|
70
|
+
case scan
|
|
71
|
+
case clearAlreadyScannedBlocks
|
|
72
|
+
case enhance
|
|
73
|
+
case fetchUTXO
|
|
74
|
+
case handleSaplingParams
|
|
75
|
+
case clearCache
|
|
76
|
+
case finished
|
|
77
|
+
case failed
|
|
78
|
+
case stopped
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protocol Action {
|
|
82
|
+
/// If this is true and action fails with error then blocks cache is cleared.
|
|
83
|
+
var removeBlocksCacheWhenFailed: Bool { get }
|
|
84
|
+
|
|
85
|
+
// When any action is created it can get `DIContainer` and resolve any depedencies it requires.
|
|
86
|
+
// Every action uses `context` to get some informartion like download range.
|
|
87
|
+
//
|
|
88
|
+
// `didUpdate` is closure that action use to tell CBP that some part of the work is done. For example if download action would like to
|
|
89
|
+
// update progress on every block downloaded it can use this closure. Also if action doesn't need to update progress on partial work it doesn't
|
|
90
|
+
// need to use this closure at all.
|
|
91
|
+
//
|
|
92
|
+
// Each action updates context accordingly. It should at least set new state. Reason for this is that action can return different states for
|
|
93
|
+
// different conditions. And action is the thing that knows these conditions.
|
|
94
|
+
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext
|
|
95
|
+
|
|
96
|
+
// Should be called on each existing action when processor wants to stop. Some actions may do it's own background work.
|
|
97
|
+
func stop() async
|
|
98
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ClearCacheForLastScannedBatch.swift
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Created by Michal Fousek on 08.05.2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
final class ClearAlreadyScannedBlocksAction {
|
|
11
|
+
let storage: CompactBlockRepository
|
|
12
|
+
let transactionRepository: TransactionRepository
|
|
13
|
+
|
|
14
|
+
init(container: DIContainer) {
|
|
15
|
+
storage = container.resolve(CompactBlockRepository.self)
|
|
16
|
+
transactionRepository = container.resolve(TransactionRepository.self)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
extension ClearAlreadyScannedBlocksAction: Action {
|
|
21
|
+
var removeBlocksCacheWhenFailed: Bool { false }
|
|
22
|
+
|
|
23
|
+
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
|
24
|
+
guard let lastScannedHeight = await context.lastScannedHeight else {
|
|
25
|
+
throw ZcashError.compactBlockProcessorLastScannedHeight
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try await storage.clear(upTo: lastScannedHeight)
|
|
29
|
+
|
|
30
|
+
await context.update(state: .enhance)
|
|
31
|
+
return context
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func stop() async { }
|
|
35
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ClearCacheAction.swift
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Created by Michal Fousek on 05.05.2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
final class ClearCacheAction {
|
|
11
|
+
let storage: CompactBlockRepository
|
|
12
|
+
|
|
13
|
+
init(container: DIContainer) {
|
|
14
|
+
storage = container.resolve(CompactBlockRepository.self)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extension ClearCacheAction: Action {
|
|
19
|
+
var removeBlocksCacheWhenFailed: Bool { false }
|
|
20
|
+
|
|
21
|
+
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
|
22
|
+
try await storage.clear()
|
|
23
|
+
|
|
24
|
+
await context.update(state: .processSuggestedScanRanges)
|
|
25
|
+
|
|
26
|
+
return context
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func stop() async { }
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//
|
|
2
|
+
// DownloadAction.swift
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Created by Michal Fousek on 05.05.2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
final class DownloadAction {
|
|
11
|
+
let configProvider: CompactBlockProcessor.ConfigProvider
|
|
12
|
+
let downloader: BlockDownloader
|
|
13
|
+
let transactionRepository: TransactionRepository
|
|
14
|
+
let logger: Logger
|
|
15
|
+
|
|
16
|
+
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
|
17
|
+
self.configProvider = configProvider
|
|
18
|
+
downloader = container.resolve(BlockDownloader.self)
|
|
19
|
+
transactionRepository = container.resolve(TransactionRepository.self)
|
|
20
|
+
logger = container.resolve(Logger.self)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private func update(context: ActionContext) async -> ActionContext {
|
|
24
|
+
await context.update(state: .scan)
|
|
25
|
+
return context
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
extension DownloadAction: Action {
|
|
30
|
+
var removeBlocksCacheWhenFailed: Bool { true }
|
|
31
|
+
|
|
32
|
+
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
|
33
|
+
guard let lastScannedHeight = await context.lastScannedHeight else {
|
|
34
|
+
return await update(context: context)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let config = await configProvider.config
|
|
38
|
+
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
|
39
|
+
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `downloadRange` are downloaded.
|
|
40
|
+
// So the right range for this batch must be computed.
|
|
41
|
+
let batchRangeStart = lastScannedHeight
|
|
42
|
+
let batchRangeEnd = min(latestBlockHeight, batchRangeStart + config.batchSize)
|
|
43
|
+
|
|
44
|
+
guard batchRangeStart <= batchRangeEnd else {
|
|
45
|
+
return await update(context: context)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let batchRange = batchRangeStart...batchRangeEnd
|
|
49
|
+
let potentialDownloadLimit = batchRange.upperBound + (2 * config.batchSize)
|
|
50
|
+
let downloadLimit = await context.syncControlData.latestBlockHeight >= potentialDownloadLimit ? potentialDownloadLimit : batchRangeEnd
|
|
51
|
+
|
|
52
|
+
logger.debug("Starting download with range: \(batchRangeStart)...\(batchRangeEnd)")
|
|
53
|
+
|
|
54
|
+
await downloader.update(latestDownloadedBlockHeight: batchRangeStart, force: true)
|
|
55
|
+
try await downloader.setSyncRange(lastScannedHeight...latestBlockHeight, batchSize: config.batchSize)
|
|
56
|
+
await downloader.setDownloadLimit(downloadLimit)
|
|
57
|
+
await downloader.startDownload(maxBlockBufferSize: config.downloadBufferSize)
|
|
58
|
+
|
|
59
|
+
try await downloader.waitUntilRequestedBlocksAreDownloaded(in: batchRange)
|
|
60
|
+
|
|
61
|
+
return await update(context: context)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func stop() async {
|
|
65
|
+
await downloader.stopDownload()
|
|
66
|
+
}
|
|
67
|
+
}
|