Error handling refactor (#170)
* Improve error handling on processor and service * Error Refactoring * fix XCode12 issue * Fix Compilation errors and test * bump MIDDLE version
This commit is contained in:
parent
b214a19724
commit
251b4c7aa3
|
@ -6,7 +6,7 @@ target 'ZcashLightClientSample' do
|
|||
pod "KRProgressHUD"
|
||||
# Pods for ZcashLightClientSample
|
||||
pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests']
|
||||
pod 'gRPC-Swift', '~> 1.0.0-alpha.11'
|
||||
pod 'gRPC-Swift', '= 1.0.0-alpha.17'
|
||||
pod 'PaginatedTableView'
|
||||
pod 'NotificationBubbles'
|
||||
pod 'MnemonicSwift'
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
PODS:
|
||||
- CGRPCZlib (1.0.0-alpha.14)
|
||||
- CNIOAtomics (2.18.0)
|
||||
- CNIOBoringSSL (2.7.4)
|
||||
- CNIOBoringSSLShims (2.7.4):
|
||||
- CNIOBoringSSL (= 2.7.4)
|
||||
- CNIODarwin (2.18.0)
|
||||
- CNIOHTTPParser (2.18.0)
|
||||
- CNIOLinux (2.18.0)
|
||||
- CNIOSHA1 (2.18.0)
|
||||
- gRPC-Swift (1.0.0-alpha.14):
|
||||
- CGRPCZlib (= 1.0.0-alpha.14)
|
||||
- CGRPCZlib (1.0.0-alpha.17)
|
||||
- CNIOAtomics (2.20.2)
|
||||
- CNIOBoringSSL (2.9.0)
|
||||
- CNIOBoringSSLShims (2.9.0):
|
||||
- CNIOBoringSSL (= 2.9.0)
|
||||
- CNIODarwin (2.20.2)
|
||||
- CNIOHTTPParser (2.20.2)
|
||||
- CNIOLinux (2.20.2)
|
||||
- CNIOSHA1 (2.20.2)
|
||||
- gRPC-Swift (1.0.0-alpha.17):
|
||||
- CGRPCZlib (= 1.0.0-alpha.17)
|
||||
- Logging (< 2, >= 1.2.0)
|
||||
- SwiftNIO (< 3, >= 2.18.0)
|
||||
- SwiftNIO (< 3, >= 2.19.0)
|
||||
- SwiftNIOHTTP2 (< 2, >= 1.12.2)
|
||||
- SwiftNIOSSL (< 3, >= 2.7.4)
|
||||
- SwiftNIOSSL (< 3, >= 2.8.0)
|
||||
- SwiftNIOTransportServices (< 2, >= 1.6.0)
|
||||
- SwiftProtobuf (< 2, >= 1.9.0)
|
||||
- KRActivityIndicatorView (3.0.5)
|
||||
- KRProgressHUD (3.4.5):
|
||||
- KRActivityIndicatorView (= 3.0.5)
|
||||
- Logging (1.2.0)
|
||||
- Logging (1.4.0)
|
||||
- MnemonicSwift (1.0.0)
|
||||
- NotificationBubbles (0.1.1)
|
||||
- PaginatedTableView (1.0.1)
|
||||
- SQLite.swift (0.12.2):
|
||||
- SQLite.swift/standard (= 0.12.2)
|
||||
- SQLite.swift/standard (0.12.2)
|
||||
- SwiftNIO (2.18.0):
|
||||
- CNIOAtomics (= 2.18.0)
|
||||
- CNIODarwin (= 2.18.0)
|
||||
- CNIOLinux (= 2.18.0)
|
||||
- CNIOSHA1 (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (2.18.0):
|
||||
- CNIOAtomics (= 2.18.0)
|
||||
- SwiftNIOFoundationCompat (2.18.0):
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOHPACK (1.12.2):
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.18.0)
|
||||
- SwiftNIOHTTP1 (= 2.18.0)
|
||||
- SwiftNIOHTTP1 (2.18.0):
|
||||
- CNIOHTTPParser (= 2.18.0)
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.18.0)
|
||||
- SwiftNIOHTTP2 (1.12.2):
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.18.0)
|
||||
- SwiftNIOHPACK (= 1.12.2)
|
||||
- SwiftNIOHTTP1 (= 2.18.0)
|
||||
- SwiftNIOTLS (= 2.18.0)
|
||||
- SwiftNIOSSL (2.7.4):
|
||||
- CNIOBoringSSL (= 2.7.4)
|
||||
- CNIOBoringSSLShims (= 2.7.4)
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.18.0)
|
||||
- SwiftNIOTLS (= 2.18.0)
|
||||
- SwiftNIOTLS (2.18.0):
|
||||
- SwiftNIO (= 2.18.0)
|
||||
- SwiftNIOTransportServices (1.6.0):
|
||||
- SwiftNIO (~> 2.0)
|
||||
- SwiftNIOConcurrencyHelpers (~> 2.0)
|
||||
- SwiftNIOFoundationCompat (~> 2.0)
|
||||
- SwiftNIOTLS (~> 2.0)
|
||||
- SwiftProtobuf (1.9.0)
|
||||
- SwiftNIO (2.20.2):
|
||||
- CNIOAtomics (= 2.20.2)
|
||||
- CNIODarwin (= 2.20.2)
|
||||
- CNIOLinux (= 2.20.2)
|
||||
- CNIOSHA1 (= 2.20.2)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.20.2)
|
||||
- SwiftNIOConcurrencyHelpers (2.20.2):
|
||||
- CNIOAtomics (= 2.20.2)
|
||||
- SwiftNIOFoundationCompat (2.20.2):
|
||||
- SwiftNIO (= 2.20.2)
|
||||
- SwiftNIOHPACK (1.13.0):
|
||||
- SwiftNIO (< 3, >= 2.19.0)
|
||||
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
|
||||
- SwiftNIOHTTP1 (< 3, >= 2.19.0)
|
||||
- SwiftNIOHTTP1 (2.20.2):
|
||||
- CNIOHTTPParser (= 2.20.2)
|
||||
- SwiftNIO (= 2.20.2)
|
||||
- SwiftNIOConcurrencyHelpers (= 2.20.2)
|
||||
- SwiftNIOHTTP2 (1.13.0):
|
||||
- SwiftNIO (< 3, >= 2.19.0)
|
||||
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
|
||||
- SwiftNIOHPACK (= 1.13.0)
|
||||
- SwiftNIOHTTP1 (< 3, >= 2.19.0)
|
||||
- SwiftNIOTLS (< 3, >= 2.19.0)
|
||||
- SwiftNIOSSL (2.9.0):
|
||||
- CNIOBoringSSL (= 2.9.0)
|
||||
- CNIOBoringSSLShims (= 2.9.0)
|
||||
- SwiftNIO (< 3, >= 2.19.0)
|
||||
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
|
||||
- SwiftNIOTLS (< 3, >= 2.19.0)
|
||||
- SwiftNIOTLS (2.20.2):
|
||||
- SwiftNIO (= 2.20.2)
|
||||
- SwiftNIOTransportServices (1.8.0):
|
||||
- SwiftNIO (< 3, >= 2.19.0)
|
||||
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
|
||||
- SwiftNIOFoundationCompat (< 3, >= 2.19.0)
|
||||
- SwiftNIOTLS (< 3, >= 2.19.0)
|
||||
- SwiftProtobuf (1.11.0)
|
||||
- ZcashLightClientKit (0.5.3):
|
||||
- gRPC-Swift (~> 1.0.0-alpha.11)
|
||||
- gRPC-Swift (~> 1.0.0-alpha.17)
|
||||
- SQLite.swift (~> 0.12.2)
|
||||
- ZcashLightClientKit/Tests (0.5.3):
|
||||
- gRPC-Swift (~> 1.0.0-alpha.11)
|
||||
- gRPC-Swift (~> 1.0.0-alpha.11, ~> 1.0.0-alpha.17)
|
||||
- SQLite.swift (~> 0.12.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- gRPC-Swift (~> 1.0.0-alpha.11)
|
||||
- gRPC-Swift (= 1.0.0-alpha.17)
|
||||
- KRProgressHUD
|
||||
- MnemonicSwift
|
||||
- NotificationBubbles
|
||||
|
@ -114,34 +114,34 @@ EXTERNAL SOURCES:
|
|||
:path: "../../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
CGRPCZlib: 06247b0687f3a3edbfbfb204d53721c3ba262a34
|
||||
CNIOAtomics: b6053043649c8b9afbf2560d9d64899d5d7ce368
|
||||
CNIOBoringSSL: 21bbd36e5a68c9d2ea1aea7bfea10eea60d25a82
|
||||
CNIOBoringSSLShims: e9e57b1fd0e060a25f2f3b0b944cc84dd272368f
|
||||
CNIODarwin: 2e814fe13ee1b16a6d7603affbd95b3fbf1e65b1
|
||||
CNIOHTTPParser: 215fe669981deb6b7e4533b0b42a01e5c165d8ac
|
||||
CNIOLinux: 45e91eaba50bb850a48135aabbd7671625f15188
|
||||
CNIOSHA1: f8f5b0c8cbd067c195d1b44ab237927765bd4914
|
||||
gRPC-Swift: fb8ff0d8cdd5a020c170ba827f50c393ae31e307
|
||||
CGRPCZlib: 245283cd656bf0c309a48a887c27865d6f54f7ef
|
||||
CNIOAtomics: 7daf6423d00650104436c5f8a2a341679104ae83
|
||||
CNIOBoringSSL: fb66746214b40dded1a8ddf2e078af0eff07bfb8
|
||||
CNIOBoringSSLShims: c7a6e1e29088739872e51f70f8305beadfa6ca61
|
||||
CNIODarwin: 65509d8e6a65a3f3f7bf5b09455cbabd535f48f3
|
||||
CNIOHTTPParser: ec6aa14852274b383a52bacd4d6bb3d2432a50e9
|
||||
CNIOLinux: 380e2601f1f32f8f32a78437c5f4f5a688205e2b
|
||||
CNIOSHA1: 5cc4fc5054beeb21c8e0017ad6bf559ce8095c10
|
||||
gRPC-Swift: 871cf2df24d9f5424763ae5af7248ed26a1b1314
|
||||
KRActivityIndicatorView: 912bc0413d98340f384b12a4e1e6aa8f42fb377d
|
||||
KRProgressHUD: df4cdc3a1baf708d4276a089ee34d133fa9a6f3e
|
||||
Logging: 7838d379d234d7e5ae1265fa02804a9084caf04c
|
||||
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
||||
MnemonicSwift: d743ec3dcc1cdce706a1876dba0b6250ad1ef90d
|
||||
NotificationBubbles: 91ee10deee54f35b5d49a161e1cb3d788ab5d011
|
||||
PaginatedTableView: 294d9831d5ddf5c0dcfbb4a281d4fcfb8d12f55a
|
||||
SQLite.swift: d2b4642190917051ce6bd1d49aab565fe794eea3
|
||||
SwiftNIO: c17d311e9006fc10c1d17fbc6a7a9cb21aa46368
|
||||
SwiftNIOConcurrencyHelpers: 69762a04ed76d7254012e1f17787ee162d2cf764
|
||||
SwiftNIOFoundationCompat: 9af7b2e265c4d55eb8599a515d63784c2691dc39
|
||||
SwiftNIOHPACK: 871e4e893ecc1aeaf74435b73c13240f50d6853c
|
||||
SwiftNIOHTTP1: 67eafb3f27c3aee867dc4c0ec947e2ab71f1e2ce
|
||||
SwiftNIOHTTP2: c7ce23b714868de63dae083478b40da20d933e08
|
||||
SwiftNIOSSL: 0f28ad98a39b4c625196c2c8f154a4fded66bd96
|
||||
SwiftNIOTLS: 78c6d6798ea29f7eb0a4e1214a00bc8f07e7390c
|
||||
SwiftNIOTransportServices: 775bcda101a0d921feb69d79b5884acfce0fc0f2
|
||||
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
|
||||
ZcashLightClientKit: 45c910a419418feb081e53d179875f740091812e
|
||||
SwiftNIO: a3c1b37da3e97ce44b3cfafc61c05fe0cac540b8
|
||||
SwiftNIOConcurrencyHelpers: cd7afc3d1f1ceaf55bbd030e7d1a469d3024db92
|
||||
SwiftNIOFoundationCompat: 573f44d5b24f7ead54b6b111264c0a420fc6eccf
|
||||
SwiftNIOHPACK: 0346ad2091511232c8cf19a6183b9c96ce33baf3
|
||||
SwiftNIOHTTP1: b54fae8700b647e908597aa7ed3370389f634b87
|
||||
SwiftNIOHTTP2: 8a0f333b99f9283f457762f58baa30acfee354cb
|
||||
SwiftNIOSSL: 3e67b565a567c20ed38586ae0b3566f190776a95
|
||||
SwiftNIOTLS: 9225a214c2483873406322d83c9db3731d8350e9
|
||||
SwiftNIOTransportServices: e69704b2d41b68a531bf3aa0177fec81ba1361e6
|
||||
SwiftProtobuf: f889fe5772f90ef7d7b8aac352d1fddf39650713
|
||||
ZcashLightClientKit: 52c03806e721784c91b87a2ab038ee302e1635b9
|
||||
|
||||
PODFILE CHECKSUM: 191070101f577589f53b033656190b612695c5f7
|
||||
PODFILE CHECKSUM: 0055c060ebfda59d4243e428eedc1db06c245f19
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
|
|
|
@ -10,7 +10,7 @@ import Foundation
|
|||
import ZcashLightClientKit
|
||||
import os
|
||||
|
||||
class SampleLogger: Logger {
|
||||
class SampleLogger: ZcashLightClientKit.Logger {
|
||||
enum LogLevel: Int {
|
||||
case debug
|
||||
case error
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'ZcashLightClientKit'
|
||||
s.version = '0.5.3'
|
||||
s.version = '0.6.0'
|
||||
s.summary = 'Zcash Light Client wallet SDK for iOS'
|
||||
|
||||
s.description = <<-DESC
|
||||
|
@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|||
s.module_map = 'ZcashLightClientKit.modulemap'
|
||||
s.swift_version = '5.1'
|
||||
s.ios.deployment_target = '12.0'
|
||||
s.dependency 'gRPC-Swift', '~> 1.0.0-alpha.11'
|
||||
s.dependency 'gRPC-Swift', '~> 1.0.0-alpha.17'
|
||||
s.dependency 'SQLite.swift', '~> 0.12.2'
|
||||
s.ios.vendored_libraries = 'lib/libzcashlc.a'
|
||||
s.preserve_paths = ['Scripts', 'rust','docs','Cargo.*','ZcashLightClientKit/Stencil']
|
||||
|
|
|
@ -16,10 +16,13 @@ public enum CompactBlockProcessorError: Error {
|
|||
case invalidConfiguration
|
||||
case missingDbPath(path: String)
|
||||
case dataDbInitFailed(path: String)
|
||||
case connectionError(message: String)
|
||||
case connectionError(underlyingError: Error)
|
||||
case grpcError(statusCode: Int, message: String)
|
||||
case connectionTimeout
|
||||
case generalError(message: String)
|
||||
case maxAttemptsReached(attempts: Int)
|
||||
case unspecifiedError(underlyingError: Error)
|
||||
case criticalError
|
||||
}
|
||||
/**
|
||||
CompactBlockProcessor notification userInfo object keys.
|
||||
|
@ -686,16 +689,9 @@ public class CompactBlockProcessor {
|
|||
NotificationCenter.default.post(name: Notification.Name.blockProcessorFailed, object: self, userInfo: [CompactBlockProcessorNotificationKey.error: mapError(err)])
|
||||
}
|
||||
// TODO: encapsulate service errors better
|
||||
func mapError(_ error: Error) -> Error {
|
||||
func mapError(_ error: Error) -> CompactBlockProcessorError {
|
||||
if let lwdError = error as? LightWalletServiceError {
|
||||
switch lwdError {
|
||||
case .failed(let statusCode, let message):
|
||||
return CompactBlockProcessorError.connectionError(message: "Connection failed - Status code: \(statusCode) - message: \(message)")
|
||||
case .invalidBlock:
|
||||
return CompactBlockProcessorError.generalError(message: "Invalid block: \(lwdError)")
|
||||
default:
|
||||
return CompactBlockProcessorError.generalError(message: "Error: \(lwdError)")
|
||||
}
|
||||
return lwdError.mapToProcessorError()
|
||||
} else if let rpcError = error as? GRPC.GRPCStatus {
|
||||
switch rpcError {
|
||||
case .ok:
|
||||
|
@ -707,7 +703,7 @@ public class CompactBlockProcessor {
|
|||
|
||||
}
|
||||
}
|
||||
return error
|
||||
return .unspecifiedError(underlyingError: error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,6 +717,30 @@ public extension CompactBlockProcessor.Configuration {
|
|||
}
|
||||
}
|
||||
|
||||
extension LightWalletServiceError {
|
||||
func mapToProcessorError() -> CompactBlockProcessorError {
|
||||
switch self {
|
||||
case .failed(let statusCode, let message):
|
||||
return CompactBlockProcessorError.grpcError(statusCode: statusCode, message: message)
|
||||
case .invalidBlock:
|
||||
return CompactBlockProcessorError.generalError(message: "\(self)")
|
||||
case .generalError(let message):
|
||||
return CompactBlockProcessorError.generalError(message: message)
|
||||
case .sentFailed(let error):
|
||||
return CompactBlockProcessorError.connectionError(underlyingError: error)
|
||||
case .genericError(let error):
|
||||
return CompactBlockProcessorError.unspecifiedError(underlyingError: error)
|
||||
case .timeOut:
|
||||
return CompactBlockProcessorError.connectionTimeout
|
||||
case .criticalError:
|
||||
return CompactBlockProcessorError.criticalError
|
||||
case .userCancelled:
|
||||
return CompactBlockProcessorError.connectionTimeout
|
||||
case .unknown:
|
||||
return CompactBlockProcessorError.unspecifiedError(underlyingError: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
extension CompactBlockProcessor.State: Equatable {
|
||||
public static func == (lhs: CompactBlockProcessor.State, rhs: CompactBlockProcessor.State) -> Bool {
|
||||
switch lhs {
|
||||
|
|
|
@ -9,8 +9,24 @@
|
|||
import Foundation
|
||||
import GRPC
|
||||
import NIO
|
||||
import NIOHPACK
|
||||
public typealias Channel = GRPC.GRPCChannel
|
||||
|
||||
|
||||
extension TimeAmount {
|
||||
static let singleCallTimeout = TimeAmount.seconds(10)
|
||||
static let streamingCallTimeout = TimeAmount.seconds(90)
|
||||
}
|
||||
extension CallOptions {
|
||||
static var lwdCall: CallOptions {
|
||||
CallOptions(customMetadata: HPACKHeaders(),
|
||||
timeLimit: .timeout(.singleCallTimeout),
|
||||
messageEncoding: .disabled,
|
||||
requestIDProvider: .autogenerated,
|
||||
requestIDHeader: nil,
|
||||
cacheable: false)
|
||||
}
|
||||
}
|
||||
/**
|
||||
Swift GRPC implementation of Lightwalletd service */
|
||||
public class LightWalletGRPCService {
|
||||
|
@ -22,7 +38,7 @@ public class LightWalletGRPCService {
|
|||
|
||||
public init(channel: Channel) {
|
||||
self.channel = channel
|
||||
compactTxStreamer = CompactTxStreamerClient(channel: self.channel)
|
||||
compactTxStreamer = CompactTxStreamerClient(channel: self.channel, defaultCallOptions: CallOptions.lwdCall)
|
||||
}
|
||||
|
||||
public convenience init(endpoint: LightWalletEndpoint) {
|
||||
|
@ -59,9 +75,14 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
public func fetchTransaction(txId: Data) throws -> TransactionEntity {
|
||||
var txFilter = TxFilter()
|
||||
txFilter.hash = txId
|
||||
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
|
||||
|
||||
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
|
||||
do {
|
||||
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
|
||||
|
||||
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
public func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
|
||||
|
@ -73,7 +94,7 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
|
||||
switch response {
|
||||
case .failure(let error):
|
||||
result(.failure(LightWalletServiceError.genericError(error: error)))
|
||||
result(.failure(error.mapToServiceError()))
|
||||
case .success(let rawTx):
|
||||
result(.success(TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)))
|
||||
}
|
||||
|
@ -88,13 +109,13 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
response.whenComplete { (responseResult) in
|
||||
switch responseResult {
|
||||
case .failure(let e):
|
||||
result(.failure(LightWalletServiceError.genericError(error: e)))
|
||||
result(.failure(LightWalletServiceError.sentFailed(error: e)))
|
||||
case .success(let s):
|
||||
result(.success(s))
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
result(.failure(LightWalletServiceError.genericError(error: error)))
|
||||
result(.failure(error.mapToServiceError()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +124,11 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
let rawTx = RawTransaction.with { (raw) in
|
||||
raw.data = spendTransaction
|
||||
}
|
||||
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
|
||||
do {
|
||||
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
public func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
|
||||
|
@ -113,18 +138,21 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
blocks.append($0)
|
||||
})
|
||||
|
||||
do {
|
||||
_ = try response.status.wait()
|
||||
} catch {
|
||||
throw LightWalletServiceError.genericError(error: error)
|
||||
let status = try response.status.wait()
|
||||
switch status.code {
|
||||
|
||||
case .ok:
|
||||
do {
|
||||
return try blocks.asZcashCompactBlocks()
|
||||
} catch {
|
||||
LoggerProxy.error("invalid block in range: \(range) - Error: \(error)")
|
||||
throw LightWalletServiceError.genericError(error: error)
|
||||
}
|
||||
default:
|
||||
throw LightWalletServiceError.mapCode(status)
|
||||
}
|
||||
|
||||
do {
|
||||
return try blocks.asZcashCompactBlocks()
|
||||
} catch {
|
||||
LoggerProxy.error("invalid block in range: \(range) - Error: \(error)")
|
||||
throw LightWalletServiceError.genericError(error: error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
|
||||
|
@ -132,19 +160,18 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
|
||||
response.whenSuccess { (blockID) in
|
||||
guard let blockHeight = Int(exactly: blockID.height) else {
|
||||
result(.failure(LightWalletServiceError.generalError))
|
||||
result(.failure(LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")))
|
||||
return
|
||||
}
|
||||
result(.success(blockHeight))
|
||||
}
|
||||
|
||||
response.whenFailure { (error) in
|
||||
result(.failure(LightWalletServiceError.genericError(error: error)))
|
||||
result(.failure(error.mapToServiceError()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Make cancellable
|
||||
public func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
|
||||
|
||||
queue.async { [weak self] in
|
||||
|
@ -162,15 +189,16 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
do {
|
||||
result(.success(try blocks.asZcashCompactBlocks()))
|
||||
} catch {
|
||||
result(.failure(LightWalletServiceError.generalError))
|
||||
LoggerProxy.error("Error parsing compact blocks \(error)")
|
||||
result(.failure(LightWalletServiceError.invalidBlock))
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
result(Result.failure(LightWalletServiceError.failed(statusCode: status.code.rawValue, message: status.message ?? "No Message")))
|
||||
result(.failure(.mapCode(status)))
|
||||
}
|
||||
|
||||
} catch {
|
||||
result(.failure(LightWalletServiceError.genericError(error: error)))
|
||||
result(.failure(error.mapToServiceError()))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -184,5 +212,34 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
return height
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Error {
|
||||
func mapToServiceError() -> LightWalletServiceError {
|
||||
guard let grpcError = self as? GRPCStatusTransformable
|
||||
else {
|
||||
return LightWalletServiceError.genericError(error: self)
|
||||
}
|
||||
|
||||
return LightWalletServiceError.mapCode(grpcError.makeGRPCStatus())
|
||||
}
|
||||
}
|
||||
|
||||
extension LightWalletServiceError {
|
||||
static func mapCode(_ status: GRPCStatus) -> LightWalletServiceError {
|
||||
switch status.code {
|
||||
|
||||
case .ok:
|
||||
return LightWalletServiceError.unknown
|
||||
case .cancelled:
|
||||
return LightWalletServiceError.userCancelled
|
||||
case .unknown:
|
||||
return LightWalletServiceError.unknown
|
||||
|
||||
case .deadlineExceeded:
|
||||
return LightWalletServiceError.timeOut
|
||||
default:
|
||||
return LightWalletServiceError.genericError(error: status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,20 +14,24 @@ import SwiftProtobuf
|
|||
Wrapper for errors received from a Lightwalletd endpoint
|
||||
*/
|
||||
public enum LightWalletServiceError: Error {
|
||||
case generalError
|
||||
case generalError(message: String)
|
||||
case failed(statusCode: Int, message: String)
|
||||
case invalidBlock
|
||||
case sentFailed(sendResponse: LightWalletServiceResponse)
|
||||
case sentFailed(error: Error)
|
||||
case genericError(error: Error)
|
||||
case timeOut
|
||||
case criticalError
|
||||
case userCancelled
|
||||
case unknown
|
||||
}
|
||||
|
||||
extension LightWalletServiceError: Equatable {
|
||||
public static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
switch lhs {
|
||||
case .generalError:
|
||||
case .generalError(let m):
|
||||
switch rhs {
|
||||
case .generalError:
|
||||
return true
|
||||
case .generalError(let msg):
|
||||
return m == msg
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -46,18 +50,46 @@ extension LightWalletServiceError: Equatable {
|
|||
default:
|
||||
return false
|
||||
}
|
||||
case .sentFailed(let sendResponse):
|
||||
case .sentFailed(_):
|
||||
switch rhs {
|
||||
case .sentFailed(let response):
|
||||
return response.errorCode == sendResponse.errorCode
|
||||
case .sentFailed(_):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case .genericError:
|
||||
return false
|
||||
|
||||
case .timeOut:
|
||||
switch rhs {
|
||||
case .timeOut:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case .criticalError:
|
||||
switch rhs {
|
||||
case .criticalError:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case .userCancelled:
|
||||
switch rhs {
|
||||
case .userCancelled:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case .unknown:
|
||||
switch rhs {
|
||||
case .unknown:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public protocol LightWalletServiceResponse {
|
||||
|
|
|
@ -14,10 +14,13 @@ Represents errors thrown by a Synchronizer
|
|||
public enum SynchronizerError: Error {
|
||||
case initFailed(message: String)
|
||||
case syncFailed
|
||||
case connectionFailed(message: String)
|
||||
case connectionFailed(message: Error)
|
||||
case generalError(message: String)
|
||||
case maxRetryAttemptsReached(attempts: Int)
|
||||
case connectionError(status: Int, message: String)
|
||||
case networkTimeout
|
||||
case uncategorized(underlyingError: Error)
|
||||
case criticalError
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -142,15 +142,18 @@ public class SDKSynchronizer: Synchronizer {
|
|||
return
|
||||
}
|
||||
|
||||
try processor.start(retry: retry)
|
||||
do {
|
||||
try processor.start(retry: retry)
|
||||
} catch {
|
||||
throw mapError(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Stops the synchronizer
|
||||
- Throws: CompactBlockProcessorError when failures occur
|
||||
*/
|
||||
public func stop() throws {
|
||||
public func stop() {
|
||||
|
||||
defer {
|
||||
|
||||
|
@ -329,6 +332,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
guard let self = self else { return }
|
||||
if let error = notification.userInfo?[CompactBlockProcessorNotificationKey.error] as? Error {
|
||||
self.notifyFailure(error)
|
||||
} else {
|
||||
self.notifyFailure(CompactBlockProcessorError.generalError(message: "This is strange. processorFailed Call received no error message"))
|
||||
}
|
||||
self.status = .disconnected
|
||||
}
|
||||
|
@ -400,9 +405,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
}
|
||||
|
||||
@objc func applicationWillTerminate(_ notification: Notification) {
|
||||
do {
|
||||
try stop()
|
||||
} catch {}
|
||||
stop()
|
||||
}
|
||||
|
||||
// MARK: Synchronizer methods
|
||||
|
@ -547,9 +550,15 @@ public class SDKSynchronizer: Synchronizer {
|
|||
return SynchronizerError.maxRetryAttemptsReached(attempts: attempts)
|
||||
case .grpcError(let statusCode, let message):
|
||||
return SynchronizerError.connectionError(status: statusCode, message: message)
|
||||
case .connectionTimeout:
|
||||
return SynchronizerError.networkTimeout
|
||||
case .unspecifiedError(let underlyingError):
|
||||
return SynchronizerError.uncategorized(underlyingError: underlyingError)
|
||||
case .criticalError:
|
||||
return SynchronizerError.criticalError
|
||||
}
|
||||
}
|
||||
return error
|
||||
return SynchronizerError.uncategorized(underlyingError: error)
|
||||
}
|
||||
|
||||
private func notifyFailure(_ error: Error) {
|
||||
|
|
|
@ -79,14 +79,14 @@ class CompactBlockReorgTests: XCTestCase {
|
|||
}
|
||||
|
||||
@objc func processorFailed(_ notification: Notification) {
|
||||
DispatchQueue.main.sync {
|
||||
|
||||
XCTAssertNotNil(notification.userInfo)
|
||||
if let error = notification.userInfo?["error"] {
|
||||
XCTFail("CompactBlockProcessor failed with Error: \(error)")
|
||||
} else {
|
||||
XCTFail("CompactBlockProcessor failed")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fileprivate func startProcessing() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import Foundation
|
||||
import os
|
||||
import ZcashLightClientKit
|
||||
class SampleLogger: Logger {
|
||||
class SampleLogger: ZcashLightClientKit.Logger {
|
||||
enum LogLevel: Int {
|
||||
case debug
|
||||
case error
|
||||
|
|
|
@ -13,7 +13,7 @@ import SwiftProtobuf
|
|||
|
||||
class AwfulLightWalletService: MockLightWalletService {
|
||||
override func latestBlockHeight() throws -> BlockHeight {
|
||||
throw LightWalletServiceError.generalError
|
||||
throw LightWalletServiceError.criticalError
|
||||
}
|
||||
|
||||
override func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
|
||||
|
@ -22,20 +22,20 @@ class AwfulLightWalletService: MockLightWalletService {
|
|||
|
||||
override func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
result(.failure(LightWalletServiceError.generalError))
|
||||
result(.failure(LightWalletServiceError.invalidBlock))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
result(.failure(LightWalletServiceError.generalError))
|
||||
result(.failure(LightWalletServiceError.invalidBlock))
|
||||
}
|
||||
}
|
||||
|
||||
override func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse,LightWalletServiceError>) -> Void) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
result(.failure(LightWalletServiceError.generalError))
|
||||
result(.failure(LightWalletServiceError.invalidBlock))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ class AwfulLightWalletService: MockLightWalletService {
|
|||
*/
|
||||
|
||||
override func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
|
||||
throw LightWalletServiceError.generalError
|
||||
throw LightWalletServiceError.invalidBlock
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue