diff --git a/Extensions/PromiseKit/TezosNode/TezosNodeClient+Promises.swift b/Extensions/PromiseKit/TezosNode/TezosNodeClient+Promises.swift index e36470c7..96878210 100644 --- a/Extensions/PromiseKit/TezosNode/TezosNodeClient+Promises.swift +++ b/Extensions/PromiseKit/TezosNode/TezosNodeClient+Promises.swift @@ -295,7 +295,7 @@ extension TezosNodeClient { ) case .failure(let error): return Promise { seal in - seal.reject(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + seal.reject(TezosKitError.transactionFormationFailure(underlyingError: error)) } } } @@ -339,7 +339,7 @@ extension TezosNodeClient { ) case .failure(let error): return Promise { seal in - seal.reject(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + seal.reject(TezosKitError.transactionFormationFailure(underlyingError: error)) } } } @@ -374,7 +374,7 @@ extension TezosNodeClient { ) case .failure(let error): return Promise { seal in - seal.reject(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + seal.reject(TezosKitError.transactionFormationFailure(underlyingError: error)) } } } @@ -405,7 +405,7 @@ extension TezosNodeClient { ) case .failure(let error): return Promise { seal in - seal.reject(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + seal.reject(TezosKitError.transactionFormationFailure(underlyingError: error)) } } } @@ -437,7 +437,7 @@ extension TezosNodeClient { ) case .failure(let error): return Promise { seal in - seal.reject(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + seal.reject(TezosKitError.transactionFormationFailure(underlyingError: error)) } } } diff --git a/Tests/UnitTests/Extensions/PromiseKit/NetworkClientTest+Promises.swift b/Tests/UnitTests/Extensions/PromiseKit/NetworkClientTest+Promises.swift index 25c06810..94945e35 100644 --- a/Tests/UnitTests/Extensions/PromiseKit/NetworkClientTest+Promises.swift +++ b/Tests/UnitTests/Extensions/PromiseKit/NetworkClientTest+Promises.swift @@ -79,7 +79,7 @@ extension NetworkClientTest { headerFields: nil ) fakeURLSession.data = "Result".data(using: .utf8) - fakeURLSession.error = TezosKitError(kind: .unknown, underlyingError: nil) + fakeURLSession.error = TezosKitError.unknown(description: nil) let expectation = XCTestExpectation(description: "Promise is resolved") let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) diff --git a/Tests/UnitTests/TezosKit/ConseilClientTests.swift b/Tests/UnitTests/TezosKit/ConseilClientTests.swift index a2468335..a2a2a38c 100644 --- a/Tests/UnitTests/TezosKit/ConseilClientTests.swift +++ b/Tests/UnitTests/TezosKit/ConseilClientTests.swift @@ -97,27 +97,27 @@ final class ConseilClientTests: XCTestCase { func testCombineResults_aNil() { let a: Result<[Transaction], TezosKitError>? = nil - let b: Result<[Transaction], TezosKitError>? = .failure(TezosKitError(kind: .unknown)) + let b: Result<[Transaction], TezosKitError>? = .failure(.unknown(description: nil)) XCTAssertNil(ConseilClient.combine(a, b)) } func testCombineResults_bNil() { - let a: Result<[Transaction], TezosKitError>? = .failure(TezosKitError(kind: .unknown)) + let a: Result<[Transaction], TezosKitError>? = .failure(.unknown(description: nil)) let b: Result<[Transaction], TezosKitError>? = nil XCTAssertNil(ConseilClient.combine(a, b)) } func testCombineResults_bothNoNil() { - let a: Result<[Transaction], TezosKitError>? = .failure(TezosKitError(kind: .unknown)) - let b: Result<[Transaction], TezosKitError>? = .failure(TezosKitError(kind: .unknown)) + let a: Result<[Transaction], TezosKitError>? = .failure(.unknown(description: nil)) + let b: Result<[Transaction], TezosKitError>? = .failure(.unknown(description: nil)) XCTAssertNotNil(ConseilClient.combine(a, b)) } func testCombineResults_bothFailure() { - let errorA = TezosKitError(kind: .unexpectedResponse) + let errorA = TezosKitError.unexpectedResponse(description: "unepected response") let a: Result<[Transaction], TezosKitError> = .failure(errorA) - let errorB = TezosKitError(kind: .invalidURL) + let errorB = TezosKitError.invalidURL let b: Result<[Transaction], TezosKitError> = .failure(errorB) guard let result = ConseilClient.combine(a, b) else { @@ -133,7 +133,7 @@ final class ConseilClientTests: XCTestCase { } func testCombineResults_aFailure() { - let errorA = TezosKitError(kind: .unexpectedResponse) + let errorA = TezosKitError.unexpectedResponse(description: "unepected response") let a: Result<[Transaction], TezosKitError> = .failure(errorA) let b: Result<[Transaction], TezosKitError> = .success([.testTransaction]) @@ -153,7 +153,7 @@ final class ConseilClientTests: XCTestCase { func testCombineResults_bFailure() { let a: Result<[Transaction], TezosKitError> = .success([.testTransaction]) - let errorB = TezosKitError(kind: .invalidURL) + let errorB = TezosKitError.invalidURL let b: Result<[Transaction], TezosKitError> = .failure(errorB) guard let result = ConseilClient.combine(a, b) else { diff --git a/Tests/UnitTests/TezosKit/ForgingServiceTests.swift b/Tests/UnitTests/TezosKit/ForgingServiceTests.swift index df6a88a1..ac5fa575 100644 --- a/Tests/UnitTests/TezosKit/ForgingServiceTests.swift +++ b/Tests/UnitTests/TezosKit/ForgingServiceTests.swift @@ -46,7 +46,7 @@ class ForgingServiceTests: XCTestCase { case .success: XCTFail() case .failure(let error): - XCTAssertEqual(error.kind, .localForgingNotSupportedForOperation) + XCTAssertEqual(error, .localForgingNotSupportedForOperation) } forgeCompletionExpectation.fulfill() } diff --git a/Tests/UnitTests/TezosKit/NetworkClientTest.swift b/Tests/UnitTests/TezosKit/NetworkClientTest.swift index fcb4d0c5..b9f61d62 100644 --- a/Tests/UnitTests/TezosKit/NetworkClientTest.swift +++ b/Tests/UnitTests/TezosKit/NetworkClientTest.swift @@ -113,7 +113,7 @@ class NetworkClientTest: XCTestCase { headerFields: nil ) fakeURLSession.data = "Result".data(using: .utf8) - fakeURLSession.error = TezosKitError(kind: .unknown, underlyingError: nil) + fakeURLSession.error = TezosKitError.unknown(description: nil) let expectation = XCTestExpectation(description: "Completion is Called") let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) diff --git a/Tests/UnitTests/TezosKit/PreapplicationServiceTest.swift b/Tests/UnitTests/TezosKit/PreapplicationServiceTest.swift index 9e99359a..0ad22dfe 100644 --- a/Tests/UnitTests/TezosKit/PreapplicationServiceTest.swift +++ b/Tests/UnitTests/TezosKit/PreapplicationServiceTest.swift @@ -7,8 +7,9 @@ final class PreapplicationServiceTest: XCTestCase { private static let preapplyEndpoint = "/chains/main/blocks/" + .testBranch + "/helpers/preapply/operations" // swiftlint:disable line_length + private static let invalidPreapplicationResponseErrorID = "proto.003-PsddFKi3.contract.balance_too_low" private static let invalidPreapplicationResponse = - "[{\"contents\":[{\"kind\":\"transaction\",\"source\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"fee\":\"1272\",\"counter\":\"30802\",\"gas_limit\":\"10100\",\"storage_limit\":\"257\",\"amount\":\"10000000000000\",\"destination\":\"tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5\",\"metadata\":{\"balance_updates\":[{\"kind\":\"contract\",\"contract\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"change\":\"-1272\"},{\"kind\":\"freezer\",\"category\":\"fees\",\"delegate\":\"tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU\",\"level\":125,\"change\":\"1272\"}],\"operation_result\":{\"status\":\"failed\",\"errors\":[{\"kind\":\"temporary\",\"id\":\"proto.003-PsddFKi3.contract.balance_too_low\",\"contract\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"balance\":\"98751713\",\"amount\":\"10000000000000\"}]}}}],\"signature\":\"edsigu16pv1NUsXuJkwWDAqvFDbhcsRAHbdxbYJcN7AShN4yDspRmsP5kgbzs2osTHGGDkyED3vjQFcbskv3BVESJ7tpchmbbop\"}]" + "[{\"contents\":[{\"kind\":\"transaction\",\"source\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"fee\":\"1272\",\"counter\":\"30802\",\"gas_limit\":\"10100\",\"storage_limit\":\"257\",\"amount\":\"10000000000000\",\"destination\":\"tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5\",\"metadata\":{\"balance_updates\":[{\"kind\":\"contract\",\"contract\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"change\":\"-1272\"},{\"kind\":\"freezer\",\"category\":\"fees\",\"delegate\":\"tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU\",\"level\":125,\"change\":\"1272\"}],\"operation_result\":{\"status\":\"failed\",\"errors\":[{\"kind\":\"temporary\",\"id\":\"\(invalidPreapplicationResponseErrorID)\",\"contract\":\"tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW\",\"balance\":\"98751713\",\"amount\":\"10000000000000\"}]}}}],\"signature\":\"edsigu16pv1NUsXuJkwWDAqvFDbhcsRAHbdxbYJcN7AShN4yDspRmsP5kgbzs2osTHGGDkyED3vjQFcbskv3BVESJ7tpchmbbop\"}]" // swiftlint:enable line_length func testPreapplicationValidOperation() { @@ -49,7 +50,10 @@ final class PreapplicationServiceTest: XCTestCase { XCTFail() return } - XCTAssertEqual(result.kind, .preapplicationError) + XCTAssertEqual( + result, + .preapplicationError(description: PreapplicationServiceTest.invalidPreapplicationResponseErrorID) + ) preapplicationCompletionExpectation.fulfill() } @@ -71,7 +75,7 @@ final class PreapplicationServiceTest: XCTestCase { XCTFail() return } - XCTAssertEqual(result.kind, .unexpectedResponse) + XCTAssertEqual(result, .unexpectedResponse(description: "Could not parse response")) preapplicationCompletionExpectation.fulfill() } @@ -92,7 +96,12 @@ final class PreapplicationServiceTest: XCTestCase { input: PreapplicationServiceTest.invalidPreapplicationResponse.data(using: .utf8)! )! let error = PreapplicationService.preapplicationError(from: json)! - XCTAssertEqual(error.kind, .preapplicationError) - XCTAssert(error.underlyingError!.contains("contract.balance_too_low")) + + switch error { + case .preapplicationError(let errorText): + XCTAssert(errorText.contains("contract.balance_too_low")) + default: + XCTFail("Wrong error type reported") + } } } diff --git a/Tests/UnitTests/TezosKit/RPCResponseHandlerTest.swift b/Tests/UnitTests/TezosKit/RPCResponseHandlerTest.swift index c54c1d4a..9b9b1129 100644 --- a/Tests/UnitTests/TezosKit/RPCResponseHandlerTest.swift +++ b/Tests/UnitTests/TezosKit/RPCResponseHandlerTest.swift @@ -45,8 +45,7 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .unexpectedRequestFormat) - XCTAssertEqual(tezosKitError.underlyingError, RPCResponseHandlerTest.testErrorString) + XCTAssertEqual(tezosKitError, .unexpectedRequestFormat(description: RPCResponseHandlerTest.testErrorString)) case .success: XCTFail() } @@ -63,8 +62,7 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .unexpectedResponse) - XCTAssertEqual(tezosKitError.underlyingError, RPCResponseHandlerTest.testErrorString) + XCTAssertEqual(tezosKitError, .unexpectedResponse(description: RPCResponseHandlerTest.testErrorString)) case .success: XCTFail() } @@ -81,8 +79,7 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .unknown) - XCTAssertEqual(tezosKitError.underlyingError, RPCResponseHandlerTest.testErrorString) + XCTAssertEqual(tezosKitError, .unknown(description: RPCResponseHandlerTest.testErrorString)) case .success: XCTFail() } @@ -100,8 +97,12 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .rpcError) - XCTAssertEqual(tezosKitError.underlyingError, testError.localizedDescription) + switch tezosKitError { + case .rpcError(let description): + XCTAssertEqual(description, testError.localizedDescription) + default: + XCTFail("Wrong error type reported.") + } case .success: XCTFail() } @@ -135,8 +136,7 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .unexpectedResponse) - XCTAssertEqual(tezosKitError.underlyingError, nil) + XCTAssertEqual(tezosKitError, .unexpectedResponse(description: "No data in response")) case .success: XCTFail() } @@ -153,8 +153,7 @@ class RPCResponseHandlerTest: XCTestCase { switch result { case .failure(let tezosKitError): - XCTAssertEqual(tezosKitError.kind, .unexpectedResponse) - XCTAssertEqual(tezosKitError.underlyingError, nil) + XCTAssertEqual(tezosKitError, .unexpectedResponse(description: "Could not parse response")) case .success: XCTFail() } diff --git a/Tests/UnitTests/TezosKit/TezosKitErrorCodesTest.swift b/Tests/UnitTests/TezosKit/TezosKitErrorCodesTest.swift deleted file mode 100644 index 888cdf93..00000000 --- a/Tests/UnitTests/TezosKit/TezosKitErrorCodesTest.swift +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright Keefer Taylor, 2018 - -@testable import TezosKit -import XCTest - -class TezosKitErrorCodesTest: XCTestCase { - public func testLocalizedDescription() { - let errorKind: TezosKitError.ErrorKind = .unexpectedResponse - let expectedLocalizedDescription = "TezosKitError \(errorKind.rawValue)" - - let error = TezosKitError(kind: errorKind, underlyingError: nil) - - let localizedDescription = error.localizedDescription - - XCTAssertEqual(localizedDescription, expectedLocalizedDescription) - } - - public func testLocalizedDescriptionWithUnderlyingError() { - let errorKind: TezosKitError.ErrorKind = .unexpectedResponse - let errorString = "A string describing an error" - let expectedLocalizedDescription = "\(errorString) (TezosKitError \(errorKind.rawValue))" - - let error = TezosKitError(kind: errorKind, underlyingError: errorString) - - let localizedDescription = error.localizedDescription - - XCTAssertEqual(localizedDescription, expectedLocalizedDescription) - } -} diff --git a/TezosKit.xcodeproj/project.pbxproj b/TezosKit.xcodeproj/project.pbxproj index 3d794023..9bae7cfd 100644 --- a/TezosKit.xcodeproj/project.pbxproj +++ b/TezosKit.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 03CEFD213AC691D632D90FAF /* GetChainHeadHashRPCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FFED1AB3870A0537888D39E /* GetChainHeadHashRPCTest.swift */; }; 05242C7AF25D0B6C351BC765 /* GetOriginatedContractsRPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7008A9105E3151B6B23496F1 /* GetOriginatedContractsRPC.swift */; }; 053802B930B6B511932F2912 /* SomeMichelsonParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB80D50511873CF9783361B4 /* SomeMichelsonParameter.swift */; }; + 066EBDBDED05BEF21905F005 /* OperationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B809E830296682CE490A4C5 /* OperationResponse.swift */; }; 078DB916D5C442FBEAF6C207 /* CryptoSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AC64BA50EF400CF4B90951AA /* CryptoSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 083E6F479F724D868A0513C0 /* JSONUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17556CA46001F8FB5DF8302 /* JSONUtils.swift */; }; 09EDCDEF232C8F10CADD8ACD /* OperationFeePolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207E6BD1F08A190CAD16F7AA /* OperationFeePolicy.swift */; }; @@ -99,7 +100,6 @@ 39956383AC208C08BA1F8D85 /* KeyChainWallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2319DB8D9848B66780D89EBB /* KeyChainWallet.swift */; }; 3AD54821F71295B8173C3241 /* ManagerContractClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 606292A7C4D50AD99EDC7208 /* ManagerContractClient.swift */; }; 3C99F5A58A32231BE0820A4A /* GetBallotsRPCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AF9ECBC79C00C0B082798EB /* GetBallotsRPCTest.swift */; }; - 3CC9387F30A2C0880378097A /* TezosKitErrorCodesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4254B915770CD924FBBE9D /* TezosKitErrorCodesTest.swift */; }; 3D0DFC6B5FED520A51FFA5ED /* SigningService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B1E035A6252AD79E6A4AAD1 /* SigningService.swift */; }; 3DD35013DA97BA70B30E7ADF /* MnemonicKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1DD4B1012288DD6F90E8C78A /* MnemonicKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E2839CA355D9C016F8D57E8 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4515BCFCC3C373EAF8900454 /* Logger.swift */; }; @@ -293,7 +293,6 @@ 99EF9D9DD18902B98C5B2739 /* ConseilNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11388A975CDB5601AFC99189 /* ConseilNetwork.swift */; }; 9A1BE88DCC44E98E1D85C26C /* IntegerResponseAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 109F98709DCC0A5351158718 /* IntegerResponseAdapter.swift */; }; 9ACC5804F3B0BD26D25223CC /* JSONDictionaryResponseAdapterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3F1D59FA8A152B8A66043A /* JSONDictionaryResponseAdapterTest.swift */; }; - 9B22F93D4284980497E94D9E /* TezosKitErrorCodesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4254B915770CD924FBBE9D /* TezosKitErrorCodesTest.swift */; }; 9B3002D8742780ABC34C5C10 /* SimulationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BFF651BFE4E4A3E90313FA9 /* SimulationService.swift */; }; 9C490216EE45DD3B2D5FA043 /* OperationWithCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04781056C289A009489C072C /* OperationWithCounter.swift */; }; 9D76FFEA43D41606A08098FB /* SmartContractInvocationOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8938737BEDF3F8E643E42865 /* SmartContractInvocationOperationTest.swift */; }; @@ -403,6 +402,7 @@ D867A7026A6E246C8319C0E4 /* AbstractOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD5FAF254AF66B1A805ABF27 /* AbstractOperationTest.swift */; }; D8D3825EEB92B28B774C544C /* PublicKeyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB80BC8FA72641177E530F7E /* PublicKeyProtocol.swift */; }; D98B97305EDA7C6CDEEB8533 /* JSONArrayResponseAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039C325259AE4DD3416B4F30 /* JSONArrayResponseAdapter.swift */; }; + D9B7A025A831DDD052838A2C /* OperationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B809E830296682CE490A4C5 /* OperationResponse.swift */; }; DA1F8FEB719BB06EB6E0B4CF /* PublicKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DD132F238141B3A1D24CC3 /* PublicKey.swift */; }; DAB2C96A2F10A124E40ABB1A /* MnemonicKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61EDBE7577517E6ACF2498A2 /* MnemonicKit.framework */; }; DAB469501CBBA2BC3259F563 /* TransactionOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8539A22E432B9FCA2191C6F3 /* TransactionOperationTest.swift */; }; @@ -625,6 +625,7 @@ 170AD904F169111FBCD93FCC /* DelegationOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegationOperation.swift; sourceTree = ""; }; 18027B5B88EBBF5C5FD9B1F8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 18257A644A0B08F1E48E8808 /* LeftMichelsonParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftMichelsonParameter.swift; sourceTree = ""; }; + 1B809E830296682CE490A4C5 /* OperationResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationResponse.swift; sourceTree = ""; }; 1BCD5416B3E149D9389F6961 /* ConseilClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConseilClientTests.swift; sourceTree = ""; }; 1DC8C35C8541E0CBE377968D /* IntMichelsonParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntMichelsonParameter.swift; sourceTree = ""; }; 1DD4B1012288DD6F90E8C78A /* MnemonicKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MnemonicKit.framework; sourceTree = ""; }; @@ -765,7 +766,6 @@ AD2FD2E17433D630AA933B5B /* SignedProtocolOperationPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignedProtocolOperationPayload.swift; sourceTree = ""; }; AD5FAF254AF66B1A805ABF27 /* AbstractOperationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbstractOperationTest.swift; sourceTree = ""; }; AE3CEDF87CB74674EF5E2BB5 /* BytesMichelsonParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BytesMichelsonParameter.swift; sourceTree = ""; }; - AF4254B915770CD924FBBE9D /* TezosKitErrorCodesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TezosKitErrorCodesTest.swift; sourceTree = ""; }; AFC77643CD2C374042E0B932 /* CryptoSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = ""; }; B01627EE910CBE5821502281 /* GetAddressManagerKeyRPC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAddressManagerKeyRPC.swift; sourceTree = ""; }; B033280AD0AE71CF00F15555 /* PreapplyOperationRPC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreapplyOperationRPC.swift; sourceTree = ""; }; @@ -927,6 +927,7 @@ 170AD904F169111FBCD93FCC /* DelegationOperation.swift */, CE5EBE1E77B4458B18D149C1 /* Operation.swift */, 3D81337F4A5B2C502DB3D076 /* OperationKind.swift */, + 1B809E830296682CE490A4C5 /* OperationResponse.swift */, 04781056C289A009489C072C /* OperationWithCounter.swift */, 60CCD5574FD830A21601E40E /* OriginationOperation.swift */, 9497DCBC4C3BE5334CF8BC59 /* RevealOperation.swift */, @@ -1015,7 +1016,6 @@ E0B48169F083D2DAEB462840 /* SimulationServiceTest.swift */, 8938737BEDF3F8E643E42865 /* SmartContractInvocationOperationTest.swift */, CE7B474664A9C0C8EA93EA08 /* StringResponseAdapterTest.swift */, - AF4254B915770CD924FBBE9D /* TezosKitErrorCodesTest.swift */, A480E400F3C3D065639376F4 /* TezosNodeClientTests.swift */, 88F56EE382535F0A59A52E76 /* TezResponseAdapterTest.swift */, 77CF8E4119383EA36202FE25 /* TezTest.swift */, @@ -1823,7 +1823,6 @@ 6EA2C05ED0589F4D707AA291 /* TestObjects.swift in Sources */, 42942076138616B8E91C9280 /* TezResponseAdapterTest.swift in Sources */, FEFBD0AE42D0285E2DBFAEDB /* TezTest.swift in Sources */, - 3CC9387F30A2C0880378097A /* TezosKitErrorCodesTest.swift in Sources */, 59A2F834737A398C874C200B /* TezosNodeClientTests.swift in Sources */, D351C031963368534FAEBC50 /* TokenContractClientTests.swift in Sources */, DC9C8834E1D992263ED86CBA /* TransactionOperationTest.swift in Sources */, @@ -1930,6 +1929,7 @@ CD91A216AE335648B059C1C8 /* OperationMetadataProvider.swift in Sources */, 963E92E6248582A1CD1D9468 /* OperationPayload.swift in Sources */, 85BC63DB233D9E4663D05D6B /* OperationPayloadFactory.swift in Sources */, + D9B7A025A831DDD052838A2C /* OperationResponse.swift in Sources */, 346B3C1348BED784D82EF921 /* OperationWithCounter.swift in Sources */, 991D2C7E2C85AF62C0FFF390 /* OriginationOperation.swift in Sources */, F71BD51C6A8C3F5CB182AE41 /* PackDataPayload.swift in Sources */, @@ -2065,7 +2065,6 @@ 381DBFEA8AB85D0A93AD40FE /* TestObjects.swift in Sources */, C6AAFF78C788015D767EB6B8 /* TezResponseAdapterTest.swift in Sources */, 127F92545866411A37E2563A /* TezTest.swift in Sources */, - 9B22F93D4284980497E94D9E /* TezosKitErrorCodesTest.swift in Sources */, 32144B5BCBA06B8114DF0F0D /* TezosNodeClientTests.swift in Sources */, 9832CCBED4906F7744DAF714 /* TokenContractClientTests.swift in Sources */, DAB469501CBBA2BC3259F563 /* TransactionOperationTest.swift in Sources */, @@ -2155,6 +2154,7 @@ 6ADF54D797E8287A5DD92EC5 /* OperationMetadataProvider.swift in Sources */, B481FCFB6820FB7C37019455 /* OperationPayload.swift in Sources */, F20D1C720BE42B84FF5C3F60 /* OperationPayloadFactory.swift in Sources */, + 066EBDBDED05BEF21905F005 /* OperationResponse.swift in Sources */, 9C490216EE45DD3B2D5FA043 /* OperationWithCounter.swift in Sources */, FC0DA3A41819419D14A44BC8 /* OriginationOperation.swift in Sources */, 32D4E01A8FC1F543D5488856 /* PackDataPayload.swift in Sources */, diff --git a/TezosKit/Common/TezosKitError.swift b/TezosKit/Common/TezosKitError.swift index c8522c95..18e4f588 100644 --- a/TezosKit/Common/TezosKitError.swift +++ b/TezosKit/Common/TezosKitError.swift @@ -2,46 +2,16 @@ import Foundation -public struct TezosKitError: Error { - /// Enumeration representing possible kinds of errors. - public enum ErrorKind: String { - case internalError - case invalidURL - case localForgingNotSupportedForOperation - case preapplicationError - case rpcError - case signingError - case transactionFormationFailure - case unexpectedRequestFormat - case unexpectedResponse - case unknown - } - - /// The error code which occurred. - public let kind: ErrorKind - - /// The underlying error returned from a subsystem, if one exists. - public let underlyingError: String? - - public init(kind: ErrorKind, underlyingError: String? = nil) { - self.kind = kind - self.underlyingError = underlyingError - } -} - -extension TezosKitError: LocalizedError { - public var errorDescription: String? { - let errorKindDesc = "TezosKitError " + kind.rawValue - if let underlyingError = self.underlyingError { - return underlyingError + " (" + errorKindDesc + ")" - } else { - return errorKindDesc - } - } -} - -extension TezosKitError: Equatable { - public static func == (lhs: TezosKitError, rhs: TezosKitError) -> Bool { - return lhs.kind == rhs.kind && lhs.underlyingError == rhs.underlyingError - } +public indirect enum TezosKitError: Error, Equatable { + case internalError + case invalidURL + case localForgingNotSupportedForOperation + case operationError([OperationResponseInternalResultError]) + case preapplicationError(description: String) + case rpcError(description: String) + case signingError + case transactionFormationFailure(underlyingError: TezosKitError) + case unexpectedRequestFormat(description: String) + case unexpectedResponse(description: String) + case unknown(description: String?) } diff --git a/TezosKit/Conseil/ConseilClient.swift b/TezosKit/Conseil/ConseilClient.swift index 72126f2e..acd10d0b 100644 --- a/TezosKit/Conseil/ConseilClient.swift +++ b/TezosKit/Conseil/ConseilClient.swift @@ -114,7 +114,7 @@ public class ConseilClient { guard let combinedResult = ConseilClient.combine(receivedResult, sentResult) else { self.callbackQueue.async { - completion(.failure(TezosKitError(kind: .unknown))) + completion(.failure(.unknown(description: nil))) } return } diff --git a/TezosKit/Dexter/DexterExchangeClient.swift b/TezosKit/Dexter/DexterExchangeClient.swift index ff5ee6bb..d775a7ec 100644 --- a/TezosKit/Dexter/DexterExchangeClient.swift +++ b/TezosKit/Dexter/DexterExchangeClient.swift @@ -144,7 +144,7 @@ public class DexterExchangeClient { completion: @escaping (Result) -> Void ) { guard let mutezToWithdraw = Decimal(string: tezToWidthdraw.rpcRepresentation) else { - completion(.failure(TezosKitError(kind: .unknown))) + completion(.failure(.unknown(description: nil))) return } @@ -297,8 +297,8 @@ public class DexterExchangeClient { deadline: Date ) -> Result { guard let minMutezToBuy = Decimal(string: minTezToBuy.rpcRepresentation) else { - return .failure(TezosKitError(kind: .unknown)) - } + return .failure(.unknown(description: nil)) + } let parameter = PairMichelsonParameter( left: PairMichelsonParameter( diff --git a/TezosKit/Dexter/TokenContractClient.swift b/TezosKit/Dexter/TokenContractClient.swift index 2884cb7b..8c1d86d8 100644 --- a/TezosKit/Dexter/TokenContractClient.swift +++ b/TezosKit/Dexter/TokenContractClient.swift @@ -191,7 +191,7 @@ public class TokenContractClient { } // Should never reach here - return Result.failure(TezosKitError(kind: .unknown)) + return Result.failure(.unknown(description: nil)) } /// Retrieve the token balance for the given address. diff --git a/TezosKit/TezosNode/Models/Operation/OperationResponse.swift b/TezosKit/TezosNode/Models/Operation/OperationResponse.swift new file mode 100644 index 00000000..4be8e6e6 --- /dev/null +++ b/TezosKit/TezosNode/Models/Operation/OperationResponse.swift @@ -0,0 +1,93 @@ +// +// OperationResponse.swift +// SecureEnclaveExample +// +// Created by Simon Mcloughlin on 17/03/2020. +// + +import Foundation + +/// Codable version of the response object that is returned by the Tezos RPC +struct OperationResponse: Codable { + let contents: [OperationResponseContent] + + /// Check if the operation(s) has been backtracked or reversed due to a failure + func isBacktracked() -> Bool { + for content in contents { + if content.metadata.operationResult.status == "backtracked" { + return true + } + } + + return false + } + + /// Return the last error object from each internal result. The last error object is the one that contains the location of the error in the smart contract and the `with` string, giving the most debugable information + func errors() -> [OperationResponseInternalResultError] { + var errors: [OperationResponseInternalResultError] = [] + + for content in contents { + for internalResult in content.metadata.internalOperationResults { + if let error = internalResult.result.errors?.last { + errors.append(error) + } + } + } + + return errors + } +} + +struct OperationResponseContent: Codable { + let kind: String + let source: String + let metadata: OperationResponseMetadata +} + +struct OperationResponseMetadata: Codable { + let operationResult: OperationResponseResult + let internalOperationResults: [OperationResponseInternalOperation] + + private enum CodingKeys: String, CodingKey { + case operationResult = "operation_result" + case internalOperationResults = "internal_operation_results" + } +} + +struct OperationResponseResult: Codable { + let status: String + let consumedGas: String + let storageSize: String + + private enum CodingKeys: String, CodingKey { + case status + case consumedGas = "consumed_gas" + case storageSize = "storage_size" + } +} + +struct OperationResponseInternalOperation: Codable { + let kind: String + let source: String + let result: OperationResponseInternalResult +} + +struct OperationResponseInternalResult: Codable { + let status: String + let errors: [OperationResponseInternalResultError]? + + func isFailed() -> Bool { + return status == "failed" + } +} + +public struct OperationResponseInternalResultError: Codable, Equatable { + public let kind: String + public let id: String + public let location: Int? + public let with: OperationResponseInternalResultErrorWith? +} + +public struct OperationResponseInternalResultErrorWith: Codable, Equatable { + public let string: String +} diff --git a/TezosKit/TezosNode/Services/FeeEstimator.swift b/TezosKit/TezosNode/Services/FeeEstimator.swift index fac5bbea..d6a8a484 100644 --- a/TezosKit/TezosNode/Services/FeeEstimator.swift +++ b/TezosKit/TezosNode/Services/FeeEstimator.swift @@ -82,7 +82,7 @@ public class FeeEstimator { ) switch simulationResult { case .failure(let error): - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) case .success(let consumedResources): // Add safety margins for gas and storage limits. let gasLimit = consumedResources.consumedGas + SafetyMargin.gas @@ -99,9 +99,8 @@ public class FeeEstimator { operation: mutableOperation, signatureProvider: signatureProvider ) else { - let error = TezosKitError( - kind: .transactionFormationFailure, - underlyingError: "Could not calculate a fee for the size of the operation" + let error = TezosKitError.transactionFormationFailure( + underlyingError: .unknown(description: "Could not calculate a fee for the size of the operation") ) completion(.failure(error)) return @@ -132,9 +131,8 @@ public class FeeEstimator { operation: mutableOperation, signatureProvider: signatureProvider ) else { - let error = TezosKitError( - kind: .transactionFormationFailure, - underlyingError: "Could not calculate a fee for the size of the operation" + let error = TezosKitError.transactionFormationFailure( + underlyingError: .unknown(description: "Could not calculate a fee for the size of the operation") ) completion(.failure(error)) return @@ -212,7 +210,7 @@ public class FeeEstimator { case .success(let simulationResult): return .success(simulationResult) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } diff --git a/TezosKit/TezosNode/Services/ForgingService.swift b/TezosKit/TezosNode/Services/ForgingService.swift index 2e16117b..eaafbabe 100644 --- a/TezosKit/TezosNode/Services/ForgingService.swift +++ b/TezosKit/TezosNode/Services/ForgingService.swift @@ -39,7 +39,7 @@ public class ForgingService { ) -> Result { let forgingGroup = DispatchGroup() - var result: Result = .failure(TezosKitError(kind: .unknown)) + var result: Result = .failure(.unknown(description: nil)) forgingGroup.enter() forgingServiceQueue.async { self.forge(operationPayload: operationPayload, operationMetadata: operationMetadata) { forgingResult in @@ -90,7 +90,7 @@ public class ForgingService { operationMetadata: OperationMetadata ) -> Result { // Local forging is not currently supported. - let forgingUnsupportedError = TezosKitError(kind: .localForgingNotSupportedForOperation) + let forgingUnsupportedError = TezosKitError.localForgingNotSupportedForOperation return .failure(forgingUnsupportedError) } diff --git a/TezosKit/TezosNode/Services/OperationFactory.swift b/TezosKit/TezosNode/Services/OperationFactory.swift index 45f5f244..c664060f 100644 --- a/TezosKit/TezosNode/Services/OperationFactory.swift +++ b/TezosKit/TezosNode/Services/OperationFactory.swift @@ -60,7 +60,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -89,7 +89,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -120,7 +120,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -149,7 +149,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -188,7 +188,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -234,7 +234,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -279,7 +279,7 @@ public class OperationFactory { operation.operationFees = fees return .success(operation) case .failure(let error): - return .failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError)) + return .failure(.transactionFormationFailure(underlyingError: error)) } } @@ -300,7 +300,7 @@ public class OperationFactory { case .estimate: let estimationGroup = DispatchGroup() - var fees: Result = .failure(TezosKitError(kind: .unknown)) + var fees: Result = .failure(.unknown(description: nil)) estimationGroup.enter() diff --git a/TezosKit/TezosNode/Services/OperationMetadataProvider.swift b/TezosKit/TezosNode/Services/OperationMetadataProvider.swift index e87ce516..7bb36d83 100644 --- a/TezosKit/TezosNode/Services/OperationMetadataProvider.swift +++ b/TezosKit/TezosNode/Services/OperationMetadataProvider.swift @@ -37,7 +37,7 @@ public class OperationMetadataProvider { ) -> Result { let metadataGroup = DispatchGroup() - var result: Result = .failure(TezosKitError(kind: .unknown)) + var result: Result = .failure(.unknown(description: nil)) metadataGroup.enter() metadata(for: address) { metadatResult in result = metadatResult @@ -109,7 +109,7 @@ public class OperationMetadataProvider { completion(.success(metadata)) return } - completion(.failure(TezosKitError(kind: .unknown, underlyingError: "Couldn't fetch metadata"))) + completion(.failure(.unknown(description: "Couldn't fetch metadata"))) } /// Retrieve chain info counter for the given address. diff --git a/TezosKit/TezosNode/Services/PreapplicationService.swift b/TezosKit/TezosNode/Services/PreapplicationService.swift index 2d94c2f3..43770541 100644 --- a/TezosKit/TezosNode/Services/PreapplicationService.swift +++ b/TezosKit/TezosNode/Services/PreapplicationService.swift @@ -95,6 +95,6 @@ public class PreapplicationService { } return id } - return TezosKitError(kind: .preapplicationError, underlyingError: firstError) + return .preapplicationError(description: firstError) } } diff --git a/TezosKit/TezosNode/Services/RPCResponseHandler.swift b/TezosKit/TezosNode/Services/RPCResponseHandler.swift index 7247b95e..7db98dbd 100644 --- a/TezosKit/TezosNode/Services/RPCResponseHandler.swift +++ b/TezosKit/TezosNode/Services/RPCResponseHandler.swift @@ -27,28 +27,31 @@ public class RPCResponseHandler { // Check for a generic error on the request. If so, propagate. if let error = error { - let desc = error.localizedDescription - let rpcError = TezosKitError(kind: .rpcError, underlyingError: desc) + let description = error.localizedDescription + let rpcError = TezosKitError.rpcError(description: description) return .failure(rpcError) } - // Check for data - guard let data = data, let stringData = String(data: data, encoding: .utf8) else { - let tezosKitError = TezosKitError(kind: .unexpectedResponse, underlyingError: nil) - return .failure(tezosKitError) - } + // Ensure that data came back. + guard let data = data else { + return .failure(.unexpectedResponse(description: "No data in response")) + } - // Check for \"status\":\"backtracked\" in the response, indicating a failed transaction being rolledback - if stringData.contains("\"status\":\"backtracked\"") { - let tezosKitError = TezosKitError(kind: .transactionFormationFailure, underlyingError: nil) - return .failure(tezosKitError) - } + // Check for a backtracked operation response + // TODO(keefertaylor): Add a test for this logic. + do { + let operationResult = try JSONDecoder().decode(OperationResponse.self, from: data) + if operationResult.isBacktracked() { + return .failure(.operationError(operationResult.errors())) + } + } catch { + // Intentionally ignore parsing failures. Parsing only suceeds if there is an error. + } - // Ensure that valid data came back. - guard let parsedData = parse(data, with: responseAdapterClass) else { - let tezosKitError = TezosKitError(kind: .unexpectedResponse, underlyingError: nil) - return .failure(tezosKitError) - } + // Ensure that valid data came back. + guard let parsedData = parse(data, with: responseAdapterClass) else { + return .failure(.unexpectedResponse(description: "Could not parse response")) + } return .success(parsedData) } @@ -74,8 +77,7 @@ public class RPCResponseHandler { // Drop data and send our error to let subsequent handlers know something went wrong and to // give up. - let errorKind = parseErrorKind(from: httpResponse) - let error = TezosKitError(kind: errorKind, underlyingError: errorMessage) + let error = parseError(from: httpResponse, with: errorMessage) return error } @@ -83,20 +85,22 @@ public class RPCResponseHandler { /// /// - Note: This method assumes that the HTTPResponse contained an error. /// - /// - Parameter httpResponse: The HTTPURLResponse to parse. + /// - Parameters: + /// - httpResponse: The HTTPURLResponse to parse. + /// - errorMessage: An error message extracted from the response body. /// - Returns: An appropriate error kind based on the response. - private func parseErrorKind(from httpResponse: HTTPURLResponse) -> TezosKitError.ErrorKind { + private func parseError(from httpResponse: HTTPURLResponse, with errorMessage: String) -> TezosKitError { // Default to unknown error and try to give a more specific error code if it can be narrowed // down based on HTTP response code. - var errorKind: TezosKitError.ErrorKind = .unknown + var error = TezosKitError.unknown(description: errorMessage) // Status code 40X: Bad request was sent to server. if httpResponse.statusCode >= 400, httpResponse.statusCode < 500 { - errorKind = .unexpectedRequestFormat + error = .unexpectedRequestFormat(description: errorMessage) // Status code 50X: Bad request was sent to server. } else if httpResponse.statusCode >= 500, httpResponse.statusCode < 600 { - errorKind = .unexpectedResponse + error = .unexpectedResponse(description: errorMessage) } - return errorKind + return error } /// Parse the given data to an object with the given response adapter. diff --git a/TezosKit/TezosNode/Services/SimulationService.swift b/TezosKit/TezosNode/Services/SimulationService.swift index 47bc42cf..1cd5922d 100644 --- a/TezosKit/TezosNode/Services/SimulationService.swift +++ b/TezosKit/TezosNode/Services/SimulationService.swift @@ -48,7 +48,7 @@ public class SimulationService { let simulationDispatchGroup = DispatchGroup() simulationDispatchGroup.enter() - var result: Result = .failure(TezosKitError(kind: .unknown)) + var result: Result = .failure(.unknown(description: nil)) simulationServiceQueue.async { self.simulate(operation, from: source, signatureProvider: signatureProvider) { simulationResult in result = simulationResult @@ -79,7 +79,7 @@ public class SimulationService { } switch result { case .failure(let error): - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) case .success(let operationMetadata): guard let operationPayload = OperationPayloadFactory.operationPayload( @@ -94,8 +94,7 @@ public class SimulationService { signingCurve: signatureProvider.publicKey.signingCurve ) else { - let error = TezosKitError(kind: .signingError, underlyingError: nil) - completion(.failure(error)) + completion(.failure(.signingError)) return } diff --git a/TezosKit/TezosNode/TezosNodeClient.swift b/TezosKit/TezosNode/TezosNodeClient.swift index 6a28e04e..1323fd21 100644 --- a/TezosKit/TezosNode/TezosNodeClient.swift +++ b/TezosKit/TezosNode/TezosNodeClient.swift @@ -390,7 +390,7 @@ public class TezosNodeClient { ) case .failure(let error): callbackQueue.async { - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) } } } @@ -472,7 +472,7 @@ public class TezosNodeClient { ) case .failure(let error): callbackQueue.async { - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) } } } @@ -539,7 +539,7 @@ public class TezosNodeClient { ) case .failure(let error): callbackQueue.async { - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) } } } @@ -597,7 +597,7 @@ public class TezosNodeClient { ) case .failure(let error): callbackQueue.async { - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) } return } @@ -659,7 +659,7 @@ public class TezosNodeClient { ) case .failure(let error): callbackQueue.async { - completion(.failure(TezosKitError(kind: .transactionFormationFailure, underlyingError: error.underlyingError))) + completion(.failure(.transactionFormationFailure(underlyingError: error))) } } } @@ -788,8 +788,7 @@ public class TezosNodeClient { signingCurve: signatureProvider.publicKey.signingCurve ) else { - let error = TezosKitError(kind: .signingError, underlyingError: "Error signing operation.") - completion(.failure(error)) + completion(.failure(.signingError)) return }