diff --git a/Cartfile b/Cartfile index 6b58a415..99698237 100644 --- a/Cartfile +++ b/Cartfile @@ -3,3 +3,4 @@ github "keefertaylor/TezosCrypto" ~> 2.1 github "mxcl/PromiseKit" ~> 6.8 github "keefertaylor/Base58Swift" ~> 2.1 github "keefertaylor/MnemonicKit" ~> 1.3 +github "pokt-network/pocket-swift-core-carthage" diff --git a/Cartfile.resolved b/Cartfile.resolved index c1a078d3..a98d2ab3 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,8 +1,14 @@ +github "Quick/Nimble" "v8.0.4" +github "Quick/Quick" "v2.2.0" +github "RNCryptor/RNCryptor" "5.1.0" +github "ReactiveX/RxSwift" "4.5.0" github "attaswift/BigInt" "v3.1.0" github "attaswift/SipHash" "v1.2.2" github "jedisct1/swift-sodium" "0.8.0" +github "jimisaacs/SwiftKeychainWrapper" "65c16da7399dd539322203558160fa349a1e27d3" github "keefertaylor/Base58Swift" "2.1.9" github "keefertaylor/MnemonicKit" "1.3.10" github "keefertaylor/TezosCrypto" "2.1.5" github "krzyzanowskim/CryptoSwift" "0.14.0" github "mxcl/PromiseKit" "6.12.0" +github "pokt-network/pocket-swift-core-carthage" "0.0.1" diff --git a/Tests/TezosKit/PocketNetworkClientTest.swift b/Tests/TezosKit/PocketNetworkClientTest.swift new file mode 100644 index 00000000..a8a95b56 --- /dev/null +++ b/Tests/TezosKit/PocketNetworkClientTest.swift @@ -0,0 +1,200 @@ +// Copyright Keefer Taylor, 2019. + +@testable import TezosKit +import XCTest + +class PocketNetworkClientTest: XCTestCase { + public var networkClient: NetworkClient? + public let fakeURLSession = FakeURLSession() + public let callbackQueue: DispatchQueue = DispatchQueue(label: "callbackQueue") + public var pocket_dev_id = "" + // Setup + public override func setUp() { + super.setUp() + + if let path = Bundle(for: type(of: self)).path(forResource: "ci_config", ofType: "json") { + do { + let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) + let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) + if let jsonResult = jsonResult as? Dictionary, let dev_id = jsonResult["POCKET_DEV_ID"] as? String { + self.pocket_dev_id = dev_id + } + } catch { + print("Failed to retrieve the Pocket DevID with error: \(error)") + XCTFail() + } + } + // Initialize PocketNetwork Client + networkClient = PocketNetworkClient( + devID: self.pocket_dev_id, + netID: "MAINNET", + callbackQueue: callbackQueue, + responseHandler: RPCResponseHandler() + ) + } + // test + public func testRetrieveNetworkVersion() { + let expectation = XCTestExpectation(description: "Completion is Called") + // RPC endpoint will resolve to a valid URL. + let header = Header.contentTypeApplicationJSON + let rpc = RPC(endpoint: "/network/version", headers: [header], responseAdapterClass: StringResponseAdapter.self, payload: nil) + + networkClient?.send(rpc, completion: { (result) in + switch result { + case .failure: + XCTFail() + case .success: + expectation.fulfill() + } + }) + + wait(for: [expectation], timeout: 10) + } + public func testCallbackOnCorrectQueueForBadURL() { + let expectation = XCTestExpectation(description: "Completion is Called") + // RPC endpoint will not resolve to a valid URL. + let rpc = RPC(endpoint: "/ /\"test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { _ in + if #available(iOS 10, OSX 10.12, *) { + dispatchPrecondition(condition: .onQueue(self.callbackQueue)) + } + expectation.fulfill() + } + wait(for: [expectation], timeout: 10) + } + public func testCallbackOnCorrectQueue() { + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { _ in + if #available(iOS 10, OSX 10.12, *) { + dispatchPrecondition(condition: .onQueue(self.callbackQueue)) + } + expectation.fulfill() + } + wait(for: [expectation], timeout: 10) + } + public func testBadEndpointCompletesWithURL() { + let expectation = XCTestExpectation(description: "Completion is Called") + // RPC endpoint will not resolve to a valid URL. + let rpc = RPC(endpoint: "/ /\"test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + expectation.fulfill() + case .success: + XCTFail() + } + } + wait(for: [expectation], timeout: 20) + } + public func testBadHTTPResponseCompletesWithError() { + // Fake URL session has data but has an HTTP error code. + fakeURLSession.urlResponse = HTTPURLResponse( + url: URL(string: "http://keefertaylor.com")!, + statusCode: 400, + httpVersion: nil, + headerFields: nil + ) + fakeURLSession.data = "SomeString".data(using: .utf8) + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + expectation.fulfill() + case .success: + XCTFail() + } + } + wait(for: [expectation], timeout: 20) + } + public func testErrorCompletesWithError() { + // Valid HTTP response and data, but error is returned. + fakeURLSession.urlResponse = HTTPURLResponse( + url: URL(string: "http://keefertaylor.com")!, + statusCode: 200, + httpVersion: nil, + headerFields: nil + ) + fakeURLSession.data = "Result".data(using: .utf8) + fakeURLSession.error = TezosKitError(kind: .unknown, underlyingError: nil) + // Expectation + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + expectation.fulfill() + case .success: + XCTFail() + } + } + wait(for: [expectation], timeout: 20) + } + public func testNilDataCompletesWithError() { + // Valid HTTP response, but returned data is nil. + fakeURLSession.urlResponse = HTTPURLResponse( + url: URL(string: "http://keefertaylor.com")!, + statusCode: 200, + httpVersion: nil, + headerFields: nil + ) + // Expectation + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + expectation.fulfill() + case .success: + XCTFail() + } + } + wait(for: [expectation], timeout: 10) + } + public func testInocrrectDataCompletesWithError() { + // Response is a string but RPC attempts to decode to an int. + fakeURLSession.urlResponse = HTTPURLResponse( + url: URL(string: "http://keefertaylor.com")!, + statusCode: 200, + httpVersion: nil, + headerFields: nil + ) + // Expectation + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: IntegerResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + expectation.fulfill() + case .success: + XCTFail() + } + } + wait(for: [expectation], timeout: 10) + } + public func testRequestCompletesWithResultAndNoError() { + // A valid response with not HTTP error. + let expectedString = "Expected!" + fakeURLSession.urlResponse = HTTPURLResponse( + url: URL(string: "http://keefertaylor.com")!, + statusCode: 200, + httpVersion: nil, + headerFields: nil + ) + fakeURLSession.data = expectedString.data(using: .utf8) + // Expectation + let expectation = XCTestExpectation(description: "Completion is Called") + let rpc = RPC(endpoint: "/test", responseAdapterClass: StringResponseAdapter.self) + networkClient?.send(rpc) { result in + switch result { + case .failure: + XCTFail() + case .success(let data): + XCTAssertEqual(data, expectedString) + expectation.fulfill() + } + } + wait(for: [expectation], timeout: 10) + } +} diff --git a/TezosKit.podspec b/TezosKit.podspec index cb5e4f11..c7226ba6 100644 --- a/TezosKit.podspec +++ b/TezosKit.podspec @@ -15,11 +15,11 @@ Pod::Spec.new do |s| s.ios.deployment_target = "10.0" s.osx.deployment_target = "10.14" s.default_subspecs = 'TezosKitCore', 'TezosKitPromises' - + s.subspec 'TezosKitCore' do |ss| ss.source_files = "TezosKit/**/*.swift" ss.frameworks = 'Foundation' - + ss.ios.deployment_target = '10.0' ss.osx.deployment_target = '10.14' @@ -27,12 +27,13 @@ Pod::Spec.new do |s| ss.dependency "MnemonicKit", "~> 1.3" ss.dependency "TezosCrypto", "~> 2.1" ss.dependency "Base58Swift", "~> 2.1" + ss.dependency "PocketSwift-Core" end - + s.subspec 'TezosKitPromises' do |ss| ss.source_files = "Extensions/PromiseKit/*.swift" ss.frameworks = 'Foundation' - + ss.ios.deployment_target = '10.0' ss.osx.deployment_target = '10.14' @@ -42,5 +43,5 @@ Pod::Spec.new do |s| s.test_spec "Tests" do |test_spec| test_spec.source_files = ["Tests/*.swift", "Tests/TezosKit/*.swift", "Tests/Extensions/PromiseKit/*.swift"] - end + end end diff --git a/TezosKit.xcodeproj/project.pbxproj b/TezosKit.xcodeproj/project.pbxproj index 1bb73d27..3410edff 100644 --- a/TezosKit.xcodeproj/project.pbxproj +++ b/TezosKit.xcodeproj/project.pbxproj @@ -27,7 +27,7 @@ 7767AE3722C3F0CF0043C52C /* CodingUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7767AE3622C3F0CF0043C52C /* CodingUtilTest.swift */; }; 7767AE3D22C572300043C52C /* OperationMetadataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7767AE3C22C572300043C52C /* OperationMetadataProvider.swift */; }; 7774780522221DE50010BA4D /* NetworkClientTest+Promises.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7774780422221DE50010BA4D /* NetworkClientTest+Promises.swift */; }; - 7774780B2222281B0010BA4D /* TezosKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE359621F7DC76006ADABA /* TezosKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 7774780B2222281B0010BA4D /* TezosKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE359621F7DC76006ADABA /* TezosKit.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 7774780C222228590010BA4D /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77F4D26B221F899800D34B01 /* PromiseKit.framework */; }; 7774780F222228E50010BA4D /* PromiseKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7774780E222228E50010BA4D /* PromiseKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7776493B227616B200451DD5 /* FakeObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7776493A227616B200451DD5 /* FakeObjects.swift */; }; @@ -50,7 +50,6 @@ 779A9C74230E0824004C6575 /* TokenContractClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C73230E0824004C6575 /* TokenContractClient.swift */; }; 779A9C77230E09DB004C6575 /* TokenContractIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C76230E09DB004C6575 /* TokenContractIntegrationTests.swift */; }; 779A9C79230E2C4D004C6575 /* FeeEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C78230E2C4A004C6575 /* FeeEstimator.swift */; }; - 779A9C7D230E320C004C6575 /* FeeEstimatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C7C230E320B004C6575 /* FeeEstimatorTest.swift */; }; 779A9C80230E3CCF004C6575 /* TokenContractClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C7F230E3CCF004C6575 /* TokenContractClientTests.swift */; }; 779A9C82230E457A004C6575 /* DexterExchangeClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C81230E457A004C6575 /* DexterExchangeClient.swift */; }; 779A9C85230E4707004C6575 /* DexterExchangeClientIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779A9C84230E4707004C6575 /* DexterExchangeClientIntegrationTests.swift */; }; @@ -194,6 +193,41 @@ 77FE788822EEE42500B85B9D /* GetContractStorageRPCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FE788722EEE42500B85B9D /* GetContractStorageRPCTest.swift */; }; 77FE788A22EFF92E00B85B9D /* MichelsonAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FE788922EFF92E00B85B9D /* MichelsonAnnotation.swift */; }; 77FE788C22EFFA7100B85B9D /* MichelsonAnnotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FE788B22EFFA7100B85B9D /* MichelsonAnnotationTests.swift */; }; + C58B66C42390790A003E2E55 /* FeeEstimatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C58B66C2239077CF003E2E55 /* FeeEstimatorTest.swift */; }; + C5ABD4AA234EEDD700C779DC /* BigInt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE363021F7EF32006ADABA /* BigInt.framework */; }; + C5ABD4AB234EEDD700C779DC /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE36B521F7F3CB006ADABA /* CryptoSwift.framework */; }; + C5ABD4AC234EEDD700C779DC /* MnemonicKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE36B721F7F3D6006ADABA /* MnemonicKit.framework */; }; + C5ABD4AD234EEDD700C779DC /* PocketSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5E729552349CFB300155217 /* PocketSwift.framework */; }; + C5ABD4AE234EEDD700C779DC /* RNCryptor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4A6234EE62D00C779DC /* RNCryptor.framework */; }; + C5ABD4AF234EEDD700C779DC /* SipHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE363221F7F032006ADABA /* SipHash.framework */; }; + C5ABD4B0234EEDD700C779DC /* Sodium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77CE36B321F7F3C0006ADABA /* Sodium.framework */; }; + C5ABD4B1234EEDD700C779DC /* TezosCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77F4D2532218866E00D34B01 /* TezosCrypto.framework */; }; + C5ABD4B9234EEDD800C779DC /* RxBlocking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B2234EEDD700C779DC /* RxBlocking.framework */; }; + C5ABD4BA234EEDD800C779DC /* RxAtomic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B3234EEDD700C779DC /* RxAtomic.framework */; }; + C5ABD4BB234EEDD800C779DC /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B4234EEDD700C779DC /* RxSwift.framework */; }; + C5ABD4BC234EEDD800C779DC /* RxTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B5234EEDD700C779DC /* RxTest.framework */; }; + C5ABD4BD234EEDD800C779DC /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B6234EEDD800C779DC /* RxCocoa.framework */; }; + C5ABD4BE234EEDD800C779DC /* SwiftKeychainWrapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B7234EEDD800C779DC /* SwiftKeychainWrapper.framework */; }; + C5ABD4BF234EEDD800C779DC /* Base58Swift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5ABD4B8234EEDD800C779DC /* Base58Swift.framework */; }; + C5ABD4C0234EEFA300C779DC /* RxBlocking.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B2234EEDD700C779DC /* RxBlocking.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C1234EF0A200C779DC /* RxAtomic.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B3234EEDD700C779DC /* RxAtomic.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C2234EF0C100C779DC /* Base58Swift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B8234EEDD800C779DC /* Base58Swift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C3234EF0C100C779DC /* RxCocoa.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B6234EEDD800C779DC /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C4234EF0C100C779DC /* RxSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B4234EEDD700C779DC /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C5234EF0C100C779DC /* RxTest.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B5234EEDD700C779DC /* RxTest.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C6234EF0C100C779DC /* SwiftKeychainWrapper.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4B7234EEDD800C779DC /* SwiftKeychainWrapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C7234EF0C100C779DC /* RNCryptor.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5ABD4A6234EE62D00C779DC /* RNCryptor.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C8234EF0C100C779DC /* MnemonicKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 77CE36B721F7F3D6006ADABA /* MnemonicKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4C9234EF0C100C779DC /* CryptoSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 77CE36B521F7F3CB006ADABA /* CryptoSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4CA234EF0C100C779DC /* Sodium.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 77CE36B321F7F3C0006ADABA /* Sodium.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4CB234EF0C100C779DC /* SipHash.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 77CE363221F7F032006ADABA /* SipHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ABD4CC234EF0C100C779DC /* BigInt.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 77CE363021F7EF32006ADABA /* BigInt.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5E729512349973500155217 /* PocketNetworkClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E729502349973500155217 /* PocketNetworkClient.swift */; }; + C5E729542349BD0400155217 /* PocketNetworkClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E72952234997D200155217 /* PocketNetworkClientTest.swift */; }; + C5E729562349CFB300155217 /* PocketSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5E729552349CFB300155217 /* PocketSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5E72957234A567900155217 /* PocketSwift.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = C5E729552349CFB300155217 /* PocketSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C5ED751D23A1923500A36F7E /* ci_config.json in Resources */ = {isa = PBXBuildFile; fileRef = C5ED751C23A1923500A36F7E /* ci_config.json */; }; + C5ED751E23A1953500A36F7E /* ci_config.json in Resources */ = {isa = PBXBuildFile; fileRef = C5ED751C23A1923500A36F7E /* ci_config.json */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -204,7 +238,7 @@ remoteGlobalIDString = 77CE359521F7DC76006ADABA; remoteInfo = TezosKit; }; - 77CE35A121F7DC76006ADABA /* PBXContainerItemProxy */ = { + C5ABD4A8234EEC6400C779DC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 77CE358D21F7DC76006ADABA /* Project object */; proxyType = 1; @@ -220,8 +254,22 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 779427BF22C02AA900559A03 /* TezosCrypto.framework in CopyFiles */, + C5ABD4C2234EF0C100C779DC /* Base58Swift.framework in CopyFiles */, + C5ABD4C3234EF0C100C779DC /* RxCocoa.framework in CopyFiles */, + C5ABD4C4234EF0C100C779DC /* RxSwift.framework in CopyFiles */, + C5ABD4C5234EF0C100C779DC /* RxTest.framework in CopyFiles */, + C5ABD4C6234EF0C100C779DC /* SwiftKeychainWrapper.framework in CopyFiles */, + C5ABD4C7234EF0C100C779DC /* RNCryptor.framework in CopyFiles */, 7774780F222228E50010BA4D /* PromiseKit.framework in CopyFiles */, + 779427BF22C02AA900559A03 /* TezosCrypto.framework in CopyFiles */, + C5ABD4C8234EF0C100C779DC /* MnemonicKit.framework in CopyFiles */, + C5ABD4C9234EF0C100C779DC /* CryptoSwift.framework in CopyFiles */, + C5ABD4CA234EF0C100C779DC /* Sodium.framework in CopyFiles */, + C5ABD4CB234EF0C100C779DC /* SipHash.framework in CopyFiles */, + C5ABD4CC234EF0C100C779DC /* BigInt.framework in CopyFiles */, + C5ABD4C1234EF0A200C779DC /* RxAtomic.framework in CopyFiles */, + C5ABD4C0234EEFA300C779DC /* RxBlocking.framework in CopyFiles */, + C5E729562349CFB300155217 /* PocketSwift.framework in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -241,6 +289,7 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( + C5E72957234A567900155217 /* PocketSwift.framework in Copy Files */, ); name = "Copy Files"; runOnlyForDeploymentPostprocessing = 0; @@ -290,7 +339,6 @@ 779A9C73230E0824004C6575 /* TokenContractClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenContractClient.swift; sourceTree = ""; }; 779A9C76230E09DB004C6575 /* TokenContractIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenContractIntegrationTests.swift; sourceTree = ""; }; 779A9C78230E2C4A004C6575 /* FeeEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeeEstimator.swift; sourceTree = ""; }; - 779A9C7C230E320B004C6575 /* FeeEstimatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeeEstimatorTest.swift; sourceTree = ""; }; 779A9C7F230E3CCF004C6575 /* TokenContractClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenContractClientTests.swift; sourceTree = ""; }; 779A9C81230E457A004C6575 /* DexterExchangeClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DexterExchangeClient.swift; sourceTree = ""; }; 779A9C84230E4707004C6575 /* DexterExchangeClientIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DexterExchangeClientIntegrationTests.swift; sourceTree = ""; }; @@ -441,6 +489,19 @@ 77FE788922EFF92E00B85B9D /* MichelsonAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MichelsonAnnotation.swift; sourceTree = ""; }; 77FE788B22EFFA7100B85B9D /* MichelsonAnnotationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MichelsonAnnotationTests.swift; sourceTree = ""; }; C2BFF006F7695B932864C46D /* Pods_TezosKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TezosKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C58B66C2239077CF003E2E55 /* FeeEstimatorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeeEstimatorTest.swift; sourceTree = ""; }; + C5ABD4A6234EE62D00C779DC /* RNCryptor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RNCryptor.framework; path = Carthage/Build/iOS/RNCryptor.framework; sourceTree = ""; }; + C5ABD4B2234EEDD700C779DC /* RxBlocking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxBlocking.framework; path = Carthage/Build/iOS/RxBlocking.framework; sourceTree = ""; }; + C5ABD4B3234EEDD700C779DC /* RxAtomic.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxAtomic.framework; path = Carthage/Build/iOS/RxAtomic.framework; sourceTree = ""; }; + C5ABD4B4234EEDD700C779DC /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = Carthage/Build/iOS/RxSwift.framework; sourceTree = ""; }; + C5ABD4B5234EEDD700C779DC /* RxTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxTest.framework; path = Carthage/Build/iOS/RxTest.framework; sourceTree = ""; }; + C5ABD4B6234EEDD800C779DC /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = Carthage/Build/iOS/RxCocoa.framework; sourceTree = ""; }; + C5ABD4B7234EEDD800C779DC /* SwiftKeychainWrapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftKeychainWrapper.framework; path = Carthage/Build/iOS/SwiftKeychainWrapper.framework; sourceTree = ""; }; + C5ABD4B8234EEDD800C779DC /* Base58Swift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Base58Swift.framework; path = Carthage/Build/iOS/Base58Swift.framework; sourceTree = ""; }; + C5E729502349973500155217 /* PocketNetworkClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketNetworkClient.swift; sourceTree = ""; }; + C5E72952234997D200155217 /* PocketNetworkClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketNetworkClientTest.swift; sourceTree = ""; }; + C5E729552349CFB300155217 /* PocketSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PocketSwift.framework; path = Carthage/Build/iOS/PocketSwift.framework; sourceTree = ""; }; + C5ED751C23A1923500A36F7E /* ci_config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ci_config.json; sourceTree = SOURCE_ROOT; }; F4F69CEC90588DB51FE973FC /* Pods_TezosKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TezosKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -472,6 +533,21 @@ files = ( 7774780C222228590010BA4D /* PromiseKit.framework in Frameworks */, 7774780B2222281B0010BA4D /* TezosKit.framework in Frameworks */, + C5ABD4B9234EEDD800C779DC /* RxBlocking.framework in Frameworks */, + C5ABD4BA234EEDD800C779DC /* RxAtomic.framework in Frameworks */, + C5ABD4BB234EEDD800C779DC /* RxSwift.framework in Frameworks */, + C5ABD4BC234EEDD800C779DC /* RxTest.framework in Frameworks */, + C5ABD4BD234EEDD800C779DC /* RxCocoa.framework in Frameworks */, + C5ABD4BE234EEDD800C779DC /* SwiftKeychainWrapper.framework in Frameworks */, + C5ABD4BF234EEDD800C779DC /* Base58Swift.framework in Frameworks */, + C5ABD4AA234EEDD700C779DC /* BigInt.framework in Frameworks */, + C5ABD4AB234EEDD700C779DC /* CryptoSwift.framework in Frameworks */, + C5ABD4AC234EEDD700C779DC /* MnemonicKit.framework in Frameworks */, + C5ABD4AD234EEDD700C779DC /* PocketSwift.framework in Frameworks */, + C5ABD4AE234EEDD700C779DC /* RNCryptor.framework in Frameworks */, + C5ABD4AF234EEDD700C779DC /* SipHash.framework in Frameworks */, + C5ABD4B0234EEDD700C779DC /* Sodium.framework in Frameworks */, + C5ABD4B1234EEDD700C779DC /* TezosCrypto.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -595,6 +671,7 @@ 77CE358C21F7DC76006ADABA = { isa = PBXGroup; children = ( + C5E729552349CFB300155217 /* PocketSwift.framework */, 779427BE22C02AA800559A03 /* TezosCrypto.framework */, 7774780E222228E50010BA4D /* PromiseKit.framework */, 7791E60F21FE862600957650 /* TezosKitExample.playground */, @@ -620,6 +697,7 @@ 77CE35A321F7DC76006ADABA /* Tests */ = { isa = PBXGroup; children = ( + C5ED751C23A1923500A36F7E /* ci_config.json */, 77B1EAFB2228C03400EA4FCE /* TestObjects.swift */, 7776493A227616B200451DD5 /* FakeObjects.swift */, 77FE788322EEA29300B85B9D /* TestHelpers.swift */, @@ -633,6 +711,14 @@ 77CE362F21F7EF32006ADABA /* Frameworks */ = { isa = PBXGroup; children = ( + C5ABD4B8234EEDD800C779DC /* Base58Swift.framework */, + C5ABD4B3234EEDD700C779DC /* RxAtomic.framework */, + C5ABD4B2234EEDD700C779DC /* RxBlocking.framework */, + C5ABD4B6234EEDD800C779DC /* RxCocoa.framework */, + C5ABD4B4234EEDD700C779DC /* RxSwift.framework */, + C5ABD4B5234EEDD700C779DC /* RxTest.framework */, + C5ABD4B7234EEDD800C779DC /* SwiftKeychainWrapper.framework */, + C5ABD4A6234EE62D00C779DC /* RNCryptor.framework */, 77F4D26B221F899800D34B01 /* PromiseKit.framework */, 77F4D2532218866E00D34B01 /* TezosCrypto.framework */, 77CE36B721F7F3D6006ADABA /* MnemonicKit.framework */, @@ -771,6 +857,7 @@ 77F4D265221CCE4B00D34B01 /* NetworkClient.swift */, 77F4D25522189A5000D34B01 /* RPCResponseHandler.swift */, 77CE384621FC7ED8006ADABA /* TezosKitError.swift */, + C5E729502349973500155217 /* PocketNetworkClient.swift */, ); path = Client; sourceTree = ""; @@ -796,7 +883,7 @@ 77F4D27322221CCE00D34B01 /* TezosKit */ = { isa = PBXGroup; children = ( - 779A9C7C230E320B004C6575 /* FeeEstimatorTest.swift */, + C58B66C2239077CF003E2E55 /* FeeEstimatorTest.swift */, 77633D522247EFE20011106A /* TezosNodeClientTests.swift */, 779A9C592308634E004C6575 /* SimulationResultResponseAdapterTest.swift */, 77FE788B22EFFA7100B85B9D /* MichelsonAnnotationTests.swift */, @@ -858,6 +945,7 @@ 77CE36D021F7F49D006ADABA /* WalletTests.swift */, 7767AE3622C3F0CF0043C52C /* CodingUtilTest.swift */, 77CE35A621F7DC76006ADABA /* Info.plist */, + C5E72952234997D200155217 /* PocketNetworkClientTest.swift */, ); path = TezosKit; sourceTree = ""; @@ -922,6 +1010,7 @@ 77CE359421F7DC76006ADABA /* Resources */, 77CE362D21F7EED8006ADABA /* Copy Files */, 77CE362E21F7EEE2006ADABA /* Carthage */, + C5A6258D239942EC00EC9155 /* ShellScript */, ); buildRules = ( ); @@ -944,7 +1033,7 @@ buildRules = ( ); dependencies = ( - 77CE35A221F7DC76006ADABA /* PBXTargetDependency */, + C5ABD4A9234EEC6400C779DC /* PBXTargetDependency */, ); name = TezosKitTests; productName = TezosKitTests; @@ -1007,6 +1096,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C5ED751D23A1923500A36F7E /* ci_config.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1014,6 +1104,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C5ED751E23A1953500A36F7E /* ci_config.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1036,6 +1127,9 @@ "$(SRCROOT)/Carthage/Build/iOS/TezosCrypto.framework", "$(SRCROOT)/Carthage/Build/iOS/Base58Swift.framework", "$(SRCROOT)/Carthage/Build/iOS/PromiseKit.framework", + "$(SRCROOT)/Carthage/Build/iOS/PocketSwift.framework", + "$(SRCROOT)/Carthage/Build/iOS/RxBlocking.framework", + "$(SRCROOT)/Carthage/Build/iOS/RxAtomic.framework", ); name = Carthage; outputFileListPaths = ( @@ -1049,6 +1143,9 @@ "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/TezosCrypto.framework", "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Base58Swift.framework", "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/PromiseKit.framework", + "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/PocketSwift.framework", + "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxBlocking.framework", + "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxAtomic.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -1070,7 +1167,25 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint --strict\nelse\necho \"warning: SwiftLint not installed, run `brew install swiftlint`\"\nfi\n"; + shellScript = " +"; + }; + C5A6258D239942EC00EC9155 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nsource ~/.bash_profile\ndevID=\"{\\\"POCKET_DEV_ID\\\": \\\"$POCKET_DEV_ID\\\"}\"\necho \"${devID}\" > ci_config.json\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -1148,6 +1263,7 @@ 77CE387821FC7ED8006ADABA /* GetBallotsListRPC.swift in Sources */, 77CE386921FC7ED8006ADABA /* JSONDictionaryResponseAdapter.swift in Sources */, 77CE387421FC7ED8006ADABA /* GetAddressDelegateRPC.swift in Sources */, + C5E729512349973500155217 /* PocketNetworkClient.swift in Sources */, 779A9C5C230864EE004C6575 /* SimulationResult.swift in Sources */, 77CE384F21FC7ED8006ADABA /* Operation.swift in Sources */, 77F4D266221CCE4B00D34B01 /* NetworkClient.swift in Sources */, @@ -1218,6 +1334,7 @@ 77CE36F921F7F49F006ADABA /* GetAddressManagerKeyRPCTest.swift in Sources */, 77CE36F621F7F49F006ADABA /* GetBallotsListRPCTest.swift in Sources */, 77B69ECB22510FE200DB4319 /* ConseilPlatformTest.swift in Sources */, + C58B66C42390790A003E2E55 /* FeeEstimatorTest.swift in Sources */, 77B69EBF224E92C900DB4319 /* ConseilClientTests.swift in Sources */, 77CE36E321F7F49F006ADABA /* GetChainHeadHashRPCTest.swift in Sources */, 77CE36FA21F7F49F006ADABA /* TezosKitErrorCodesTest.swift in Sources */, @@ -1226,7 +1343,6 @@ 77FE788222EE913300B85B9D /* GetBigMapValueRPCTest.swift in Sources */, 77CE36FE21F7F49F006ADABA /* GetBallotsRPCTest.swift in Sources */, 77CE36F221F7F49F006ADABA /* JSONDictionaryResponseAdapterTest.swift in Sources */, - 779A9C7D230E320C004C6575 /* FeeEstimatorTest.swift in Sources */, 77CE36E121F7F49F006ADABA /* RevealOperationTest.swift in Sources */, 77CE36FF21F7F49F006ADABA /* PeriodKindResponseAdapterTest.swift in Sources */, 77B1EB08222A179F00EA4FCE /* OperationWithCounterTest.swift in Sources */, @@ -1242,6 +1358,7 @@ 77B69EC522510D5400DB4319 /* ConseilEntityTest.swift in Sources */, 77F4D268221CD44100D34B01 /* NetworkClientTest.swift in Sources */, 7776493B227616B200451DD5 /* FakeObjects.swift in Sources */, + C5E729542349BD0400155217 /* PocketNetworkClientTest.swift in Sources */, 779A9C87230E6606004C6575 /* DexterExchangeClientTests.swift in Sources */, 779427AF22BB1D6700559A03 /* OperationFactoryTest.swift in Sources */, 7719266022DA1E1500E63DE4 /* SimulationServiceTest.swift in Sources */, @@ -1278,10 +1395,10 @@ target = 77CE359521F7DC76006ADABA /* TezosKit */; targetProxy = 772F48AB2224894E00DF0F9D /* PBXContainerItemProxy */; }; - 77CE35A221F7DC76006ADABA /* PBXTargetDependency */ = { + C5ABD4A9234EEC6400C779DC /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 77CE359521F7DC76006ADABA /* TezosKit */; - targetProxy = 77CE35A121F7DC76006ADABA /* PBXContainerItemProxy */; + targetProxy = C5ABD4A8234EEC6400C779DC /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -1515,7 +1632,7 @@ 77CE35AE21F7DC76006ADABA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 6F6VXZUKN5; FRAMEWORK_SEARCH_PATHS = ( @@ -1523,6 +1640,7 @@ "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = Tests/TezosKit/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1538,7 +1656,7 @@ 77CE35AF21F7DC76006ADABA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 6F6VXZUKN5; FRAMEWORK_SEARCH_PATHS = ( @@ -1546,6 +1664,7 @@ "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = Tests/TezosKit/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/TezosKit/Client/PocketNetworkClient.swift b/TezosKit/Client/PocketNetworkClient.swift new file mode 100644 index 00000000..c475ad63 --- /dev/null +++ b/TezosKit/Client/PocketNetworkClient.swift @@ -0,0 +1,108 @@ +// Copyright Keefer Taylor, 2019 + +import Foundation +import PocketSwift +/// Pocket Network provides a trustless API Layer, allowing easy acccess to the Tezos Network +/// The PocketNetworkClient classs is an implementation of the NetworkClient protocol +/// Adds the necesary information to interact with the Pocket Network +public class PocketNetworkClient: NetworkClient { + /// Network name + private let network = "TEZOS" + /// Network ID + private let netID: String + /// Developer ID + /// NOTE: All Pocket tests require a DeveloperID, + /// For more information visit: https://docs.pokt.network/docs/how-to-participate + private let devID: String + /// Pocket Instance that will relay requests + private let pocket: Pocket + /// Headers which will be added to every request. + private let headers: [Header] + /// A response handler for RPCs. + private let responseHandler: RPCResponseHandler + /// The queue that callbacks from requests will be made on. + internal let callbackQueue: DispatchQueue + /// Initialize a new AbstractNetworkClient. + /// - Parameters: + /// - devID: Pocket developer identifier. + /// - netID: Tezos network identifier. + /// - headers: The path to the remote node. + /// - urlSession: The URLSession that will manage network requests. + /// - headers: Headers which will be added to every request. + /// - callbackQueue: A dispatch queue that callbacks will be made on. + /// - responseHandler: An object which will handle responses. + /// - maxNodes: (Optional) Max amount of nodes to be stored in the instance . + /// - requestTimeOut: (Optional) Maximum timeout for each request. + public init( + devID: String, + netID: String, + headers: [Header] = [], + callbackQueue: DispatchQueue, + responseHandler: RPCResponseHandler, + maxNodes: Int = 10, + requestTimeOut: Int = 10000 + ) { + self.netID = netID + self.devID = devID + self.headers = headers + self.callbackQueue = callbackQueue + self.responseHandler = responseHandler + self.pocket = Pocket(devID: devID, network: network, netID: netID, maxNodes: maxNodes, requestTimeOut: requestTimeOut) + } + public func send(_ rpc: RPC, callbackQueue: DispatchQueue?, completion: @escaping (Result) -> Void) { + + } + public func send(_ rpc: RPC, completion: @escaping (Result) -> Void) { + var httpMethod = Relay.HttpMethod.GET + var data = "" + // Check if rpc is a POST request + if rpc.isPOSTRequest { + httpMethod = Relay.HttpMethod.POST + data = rpc.payload ?? "" + } + // Add headers from RPC. + var headers = [String: String]() + for header in rpc.headers { + headers[header.field] = header.value + } + + let relay = Relay( + network: self.network, + netID: self.netID, + data: data, + devID: self.devID, + httpMethod: httpMethod, + path: rpc.endpoint, + queryParams: nil, + headers: nil + ) + + pocket.send( + relay: relay, + onSuccess: { response in + let data = response.data(using: .utf8) + let result = self.responseHandler.handleResponse( + response: nil, + data: data, + error: nil, + responseAdapterClass: rpc.responseAdapterClass + ) + self.callbackQueue.async { + completion(result) + } + }, + onError: { error in + let result = self.responseHandler.handleResponse( + response: nil, + data: nil, + error: error, + responseAdapterClass: rpc.responseAdapterClass + ) + self.callbackQueue.async { + completion(result) + } + } + ) + } + +} diff --git a/ci_config.json b/ci_config.json new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/ci_config.json @@ -0,0 +1 @@ +