diff --git a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/Models/PostNodesByAddressRequest.swift b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/Models/PostNodesByAddressRequest.swift new file mode 100644 index 0000000..b7f3a78 --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/Models/PostNodesByAddressRequest.swift @@ -0,0 +1,27 @@ +// +// PostNodesByAddressRequest.swift +// SOLARAPI +// +// Created by Viktoriia Kostyleva on 30.09.2022. +// + +import Foundation + +public struct PostNodesByAddressRequest: Codable { + let addresses: [String] + let page: Int? + + public init(addresses: [String], page: Int?) { + self.addresses = addresses + self.page = page + } +} + +// MARK: - Codable implementation + +public extension PostNodesByAddressRequest { + enum CodingKeys: String, CodingKey { + case addresses = "blockchain_addresses" + case page + } +} diff --git a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesAPITarget.swift b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesAPITarget.swift index b90f983..f7ce7d5 100644 --- a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesAPITarget.swift +++ b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesAPITarget.swift @@ -10,6 +10,7 @@ import Alamofire enum NodesAPITarget { case getNodes(GetNodesRequest) + case postNodesByAddress(PostNodesByAddressRequest) } extension NodesAPITarget: APITarget { @@ -17,6 +18,8 @@ extension NodesAPITarget: APITarget { switch self { case .getNodes: return .get + case .postNodesByAddress: + return .post } } @@ -24,6 +27,8 @@ extension NodesAPITarget: APITarget { switch self { case .getNodes: return "dvpn/getNodes" + case .postNodesByAddress: + return "dvpn/postNodesByAddress" } } @@ -31,6 +36,8 @@ extension NodesAPITarget: APITarget { switch self { case let .getNodes(request): return .requestParameters(parameters: request.dictionary ?? [:], encoding: URLEncoding.default) + case let .postNodesByAddress(request): + return .requestJSONEncodable(request) } } } diff --git a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProvider.swift b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProvider.swift index c1ae9d5..0d66064 100644 --- a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProvider.swift +++ b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProvider.swift @@ -34,6 +34,16 @@ extension NodesProvider: NodesProviderType { .validate() .responseDecodable(completionHandler: getResponseHandler(completion: completion)) } + + public func postNodesByAddress( + _ postNodesRequest: PostNodesByAddressRequest, + completion: @escaping (Result, NetworkError>) -> Void + ) { + AF + .request(request(for: .postNodesByAddress(postNodesRequest))) + .validate() + .responseDecodable(completionHandler: getResponseHandler(completion: completion)) + } } private extension NodesProvider { diff --git a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProviderType.swift b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProviderType.swift index 36affdd..8ba8630 100644 --- a/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProviderType.swift +++ b/SolardVPNCommunityCoreiOS/SOLARAPI/Providers/NodesProvider/NodesProviderType.swift @@ -13,4 +13,9 @@ public protocol NodesProviderType { _ getNodesRequest: GetNodesRequest, completion: @escaping (Result, NetworkError>) -> Void ) + + func postNodesByAddress( + _ postNodesRequest: PostNodesByAddressRequest, + completion: @escaping (Result, NetworkError>) -> Void + ) } diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj index 73e1b02..ef1fdd6 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj @@ -53,6 +53,9 @@ 923C371628E5B9DE003CFC03 /* ContextBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C371528E5B9DE003CFC03 /* ContextBuilder.swift */; }; 923C371828E5D20D003CFC03 /* GetNodesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C371728E5D20D003CFC03 /* GetNodesRequest.swift */; }; 923C371C28E5DA05003CFC03 /* OrderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C371B28E5DA05003CFC03 /* OrderType.swift */; }; + 923C372028E71D19003CFC03 /* PostNodesByAddressRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C371F28E71D19003CFC03 /* PostNodesByAddressRequest.swift */; }; + 923C372228E72C87003CFC03 /* NodesByAddressPostBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C372128E72C87003CFC03 /* NodesByAddressPostBody.swift */; }; + 923C372628EAE93E003CFC03 /* Encoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C372528EAE93E003CFC03 /* Encoder.swift */; }; 92D6B3FD28E19E20004CF9DF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B3FC28E19E20004CF9DF /* AppDelegate.swift */; }; 92D6B3FF28E19E20004CF9DF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B3FE28E19E20004CF9DF /* SceneDelegate.swift */; }; 92D6B40128E19E20004CF9DF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B40028E19E20004CF9DF /* ViewController.swift */; }; @@ -174,6 +177,9 @@ 923C371528E5B9DE003CFC03 /* ContextBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextBuilder.swift; sourceTree = ""; }; 923C371728E5D20D003CFC03 /* GetNodesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetNodesRequest.swift; sourceTree = ""; }; 923C371B28E5DA05003CFC03 /* OrderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderType.swift; sourceTree = ""; }; + 923C371F28E71D19003CFC03 /* PostNodesByAddressRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostNodesByAddressRequest.swift; sourceTree = ""; }; + 923C372128E72C87003CFC03 /* NodesByAddressPostBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodesByAddressPostBody.swift; sourceTree = ""; }; + 923C372528EAE93E003CFC03 /* Encoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encoder.swift; sourceTree = ""; }; 92D6B3F928E19E20004CF9DF /* SOLARdVPNCommunityCoreiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SOLARdVPNCommunityCoreiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 92D6B3FC28E19E20004CF9DF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 92D6B3FE28E19E20004CF9DF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -366,9 +372,9 @@ 22C3EF0828E6FEBA007DB01B /* Root */ = { isa = PBXGroup; children = ( + 923C372328E72FDA003CFC03 /* RouteCollections */, 92D6B3FC28E19E20004CF9DF /* AppDelegate.swift */, 92D6B41328E1E133004CF9DF /* DVPNServer.swift */, - 92D6B41728E2DC85004CF9DF /* NodesRouteCollection.swift */, 92D6B3FE28E19E20004CF9DF /* SceneDelegate.swift */, 92D6B40028E19E20004CF9DF /* ViewController.swift */, ); @@ -402,6 +408,23 @@ path = Context; sourceTree = ""; }; + 923C372328E72FDA003CFC03 /* RouteCollections */ = { + isa = PBXGroup; + children = ( + 923C372428E72FF0003CFC03 /* Nodes */, + ); + path = RouteCollections; + sourceTree = ""; + }; + 923C372428E72FF0003CFC03 /* Nodes */ = { + isa = PBXGroup; + children = ( + 923C372128E72C87003CFC03 /* NodesByAddressPostBody.swift */, + 92D6B41728E2DC85004CF9DF /* NodesRouteCollection.swift */, + ); + path = Nodes; + sourceTree = ""; + }; 92D6B3F028E19E20004CF9DF = { isa = PBXGroup; children = ( @@ -454,6 +477,7 @@ children = ( 22C3EEFA28E48F94007DB01B /* NotificationToken.swift */, 92D6B41D28E2F64D004CF9DF /* ClientConstants.swift */, + 923C372528EAE93E003CFC03 /* Encoder.swift */, ); path = Utilities; sourceTree = ""; @@ -509,6 +533,7 @@ 92D6B46228E47240004CF9DF /* Node.swift */, 92D6B46028E463EF004CF9DF /* NodeStatusType.swift */, 92D6B45E28E4639D004CF9DF /* OrderType.swift */, + 923C371F28E71D19003CFC03 /* PostNodesByAddressRequest.swift */, ); path = Models; sourceTree = ""; @@ -760,6 +785,7 @@ files = ( 92D6B40128E19E20004CF9DF /* ViewController.swift in Sources */, 22C3EEED28E48D9A007DB01B /* SentinelNode+Ext.swift in Sources */, + 923C372628EAE93E003CFC03 /* Encoder.swift in Sources */, 92D6B41828E2DC85004CF9DF /* NodesRouteCollection.swift in Sources */, 923C371428E5B898003CFC03 /* CommonContext.swift in Sources */, 92D6B3FD28E19E20004CF9DF /* AppDelegate.swift in Sources */, @@ -787,6 +813,7 @@ 92D6B47428E48F64004CF9DF /* Continent.swift in Sources */, 92D6B47128E47E71004CF9DF /* NodesServiceType.swift in Sources */, 22C3EEA828E4733C007DB01B /* Keychain.swift in Sources */, + 923C372228E72C87003CFC03 /* NodesByAddressPostBody.swift in Sources */, 22C3EECE28E48B52007DB01B /* PeersModel.swift in Sources */, 92D6B41E28E2F64D004CF9DF /* ClientConstants.swift in Sources */, 923C371628E5B9DE003CFC03 /* ContextBuilder.swift in Sources */, @@ -817,6 +844,7 @@ 92D6B44628E34D7C004CF9DF /* APIRequest.swift in Sources */, 92D6B42828E32900004CF9DF /* SOLARAPI.docc in Sources */, 92D6B45A28E46283004CF9DF /* NetworkError.swift in Sources */, + 923C372028E71D19003CFC03 /* PostNodesByAddressRequest.swift in Sources */, 92D6B46C28E47519004CF9DF /* Encodable+Ext.swift in Sources */, 92D6B45628E4609E004CF9DF /* APITarget.swift in Sources */, 92D6B45828E46118004CF9DF /* SOLARAPIProvider.swift in Sources */, diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Utilities/Encoder.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Utilities/Encoder.swift new file mode 100644 index 0000000..e03d8e6 --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Utilities/Encoder.swift @@ -0,0 +1,34 @@ +// +// Encoder.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Viktoriia Kostyleva on 03.10.2022. +// + +import Foundation + +enum EncoderError: LocalizedError { + case failToEncode + + var errorDescription: String? { + switch self { + case .failToEncode: + return "Fail to encode" + } + } +} + +enum Encoder { + static func encode( + model: Codable, + continuation: CheckedContinuation + ) { + do { + let result = try JSONEncoder().encode(model) + let string = String(decoding: result, as: UTF8.self) + continuation.resume(returning: string) + } catch { + continuation.resume(throwing: EncoderError.failToEncode) + } + } +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesByAddressPostBody.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesByAddressPostBody.swift new file mode 100644 index 0000000..8ec90ab --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesByAddressPostBody.swift @@ -0,0 +1,13 @@ +// +// NodesByAddressPostBody.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Viktoriia Kostyleva on 30.09.2022. +// + +import Vapor + +struct NodesByAddressPostBody: Content { + let blockchain_addresses: [String] + let page: Int? +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/NodesRouteCollection.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesRouteCollection.swift similarity index 79% rename from SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/NodesRouteCollection.swift rename to SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesRouteCollection.swift index 51cb774..ed56e36 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/NodesRouteCollection.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Nodes/NodesRouteCollection.swift @@ -12,6 +12,7 @@ struct NodesRouteCollection: RouteCollection { func boot(routes: RoutesBuilder) throws { routes.get("nodes", use: getNodes) + routes.post("nodesByAddress", use: postNodesByAddress) } } @@ -35,4 +36,13 @@ extension NodesRouteCollection { page: page ) } + + func postNodesByAddress(_ req: Request) async throws -> String { + let body = try req.content.decode(NodesByAddressPostBody.self) + + return try await context.nodesService.getNodes( + by: body.blockchain_addresses, + page: body.page + ) + } } diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesService.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesService.swift index 86707ca..a8aec22 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesService.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesService.swift @@ -45,11 +45,24 @@ extension NodesService: NodesServiceType { ) ) { result in switch result { - case let .success(success): - let result = try! JSONEncoder().encode(success) - let string = String(decoding: result, as: UTF8.self) - continuation.resume(returning: string) - + case let .success(response): + Encoder.encode(model: response, continuation: continuation) + case let .failure(error): + continuation.resume(throwing: Abort(.init(statusCode: error.code), reason: error.localizedDescription)) + } + } + }) + } + + func getNodes( + by addresses: [String], + page: Int? + ) async throws -> String { + try await withCheckedThrowingContinuation({ (continuation: CheckedContinuation) in + nodesProvider.postNodesByAddress(.init(addresses: addresses, page: page)) { result in + switch result { + case let .success(response): + Encoder.encode(model: response, continuation: continuation) case let .failure(error): continuation.resume(throwing: Abort(.init(statusCode: error.code), reason: error.localizedDescription)) } diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesServiceType.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesServiceType.swift index 709d099..c399da5 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesServiceType.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/NodesService/NodesServiceType.swift @@ -18,4 +18,9 @@ protocol NodesServiceType { query: String?, page: Int? ) async throws -> String + + func getNodes( + by: [String], + page: Int? + ) async throws -> String }