Last active
February 12, 2020 00:57
-
-
Save KevinVitale/152d2d105620062ecdcf6e9d29488032 to your computer and use it in GitHub Desktop.
ClientAPI + callAsFunction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import AnyCodable | |
#if !canImport(Darwin) | |
import FoundationNetworking | |
#endif | |
public protocol JSONRPCAPI: Codable { | |
static var prefix :String { get } | |
} | |
extension JSONRPCAPI { | |
static var version :String { "2.0" } | |
} | |
extension JSONRPCAPI { | |
public typealias Request<R: Decodable> = Web3Kit.Request<Self,R> | |
} | |
public struct Client<API: JSONRPCAPI> { | |
private let configuration :ClientConfiguration | |
private let session :URLSession | |
private let encoder :JSONEncoder | |
private let decoder = JSONDecoder() | |
fileprivate func encoded<T: Encodable>(request: T) -> URLRequest { | |
var urlRequest = URLRequest(url: configuration.url) | |
urlRequest.cachePolicy = .reloadIgnoringLocalCacheData | |
urlRequest.httpMethod = "POST" | |
urlRequest.httpBody = try? encoder.encode(request) | |
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
return urlRequest | |
} | |
fileprivate func decoded<T: Decodable>(data: Data?) -> Result<Response<T>,Swift.Error> { | |
Result<Response<T>,Swift.Error> { | |
guard let data = data else { | |
// FIXME with a .failure(/* error */) | |
fatalError("\(#file): \(#function); \(#line)") | |
} | |
return try decoder.decode(Response<T>.self, from: data) | |
} | |
} | |
fileprivate func decoded<T: Decodable>(data: Data?) -> Result<[Response<T>],Swift.Error> { | |
Result<[Response<T>],Swift.Error> { | |
guard let data = data else { | |
// FIXME with a .failure(/* error */) | |
fatalError("\(#file): \(#function); \(#line)") | |
} | |
return try decoder.decode([Response<T>].self, from: data) | |
} | |
} | |
} | |
extension Client { | |
public func callAsFunction<R: Decodable>(request: API.Request<R>, callback: @escaping (Result<Response<R>,Swift.Error>) -> ()) { | |
let task = session.dataTask(with: encoded(request: request)) { data, response, error in | |
guard error == nil else { | |
callback(.failure(error!)) | |
return | |
} | |
callback(self.decoded(data: data)) | |
} | |
task.resume() | |
} | |
public func callAsFunction(request: API.Request<AnyDecodable>..., callback: @escaping (Result<[Response<AnyDecodable>],Swift.Error>) -> ()) { | |
self.callAsFunction(request: request, callback: callback) | |
} | |
public func callAsFunction<R: Decodable>(request: [API.Request<R>], callback: @escaping (Result<[Response<R>],Swift.Error>) -> ()) { | |
let task = session.dataTask(with: encoded(request: request)) { data, response, error in | |
guard error == nil else { | |
callback(.failure(error!)) | |
return | |
} | |
callback(self.decoded(data: data)) | |
} | |
task.resume() | |
} | |
public func callAsFunction(request method: String, parameters: [Any] = [], id: Int = 1, callback: @escaping (Result<Response<AnyDecodable>,Swift.Error>) -> ()) { | |
self.callAsFunction(request: API.Request<AnyDecodable>(method, parameters: parameters, id: id), callback: callback) | |
} | |
} | |
extension Client where API == Web3 { | |
func derivedClient<API: JSONRPCAPI>() -> Client<API> { | |
.init(configuration: self.configuration, | |
session: self.session, | |
encoder: self.encoder) | |
} | |
public init(_ configuration: ClientConfiguration, session: URLSession = URLSession(configuration: .default)) { | |
self.configuration = configuration | |
self.session = session | |
self.encoder = JSONEncoder() | |
self.encoder.outputFormatting = .prettyPrinted | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public extension Client where API == Web3 { | |
var bzz: Client<Bzz> { derivedClient() } | |
var eth: Client<Eth> { derivedClient() } | |
var net: Client<Net> { derivedClient() } | |
var shh: Client<Shh> { derivedClient() } | |
} | |
public struct Web3 :JSONRPCAPI { public static let prefix :String = "web3" } | |
public struct Bzz :JSONRPCAPI { public static let prefix :String = "bzz" } | |
public struct Eth :JSONRPCAPI { public static let prefix :String = "eth" } | |
public struct Net :JSONRPCAPI { public static let prefix :String = "net" } | |
public struct Shh :JSONRPCAPI { public static let prefix :String = "shh" } | |
extension Request where API == Web3 { | |
public static func clientVersion() -> API.Request<String> { | |
"clientVersion" | |
} | |
public static func sha3(data: String, id: Int = 1) -> API.Request<String> { | |
API.Request("sha3", parameters: [data], id: id) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment