Skip to content

Commit 2a54eec

Browse files
Refactor API a bit.
1 parent 245cc0d commit 2a54eec

File tree

3 files changed

+45
-38
lines changed

3 files changed

+45
-38
lines changed

Sources/web3swift/API/HexDecodableProtocols.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
import BigInt
99

10+
public protocol APIResultType: Decodable { }
11+
12+
extension Array: APIResultType where Element: APIResultType { }
13+
14+
extension String: APIResultType { }
15+
1016
/// This is utility protocol for decoding API Responses
1117
///
1218
/// You better not use it in any other part of a bit of code except `APIResponse<T>` decoding.
@@ -15,11 +21,11 @@ import BigInt
1521
/// More than that their notation (e.g. 0x12d) are don't fit with the default Numeric decoders behaviours.
1622
/// So to work around that for generic cases we're going to force decode `APIResponse.result` field as `String`
1723
/// and then initiate it
18-
public protocol LiteralInitableFromString: APIResponseType {
24+
public protocol LiteralInitiableFromString: APIResultType {
1925
init?(from hexString: String)
2026
}
2127

22-
extension LiteralInitableFromString where Self: IntegerInitableWithRadix {
28+
extension LiteralInitiableFromString where Self: IntegerInitableWithRadix {
2329
/// This initializer is intended to init `(U)Int` from hex string with `0x` prefix.
2430
public init?(from hexString: String) {
2531
guard hexString.hasPrefix("0x") else { return nil }
@@ -29,22 +35,21 @@ extension LiteralInitableFromString where Self: IntegerInitableWithRadix {
2935
}
3036
}
3137

32-
extension Int: LiteralInitableFromString { }
3338

34-
extension UInt: LiteralInitableFromString { }
39+
extension Int: LiteralInitiableFromString { }
3540

36-
extension BigInt: LiteralInitableFromString { }
41+
extension UInt: LiteralInitiableFromString { }
3742

38-
extension BigUInt: LiteralInitableFromString { }
43+
extension BigInt: LiteralInitiableFromString { }
3944

40-
extension String: LiteralInitableFromString {
41-
public init?(from hexString: String) {
42-
self = hexString
43-
}
44-
}
45+
extension BigUInt: LiteralInitiableFromString { }
4546

47+
// This don't work without each other.
48+
//extension LiteralInitiableFromString {
49+
// public init?(from hexString: String) { return nil }
50+
//}
51+
//extension Array: LiteralInitiableFromString where Element: LiteralInitiableFromString { }
4652

47-
// ------
4853
public protocol IntegerInitableWithRadix {
4954
init?<S: StringProtocol>(_ text: S, radix: Int)
5055
}
@@ -56,4 +61,3 @@ extension UInt: IntegerInitableWithRadix { }
5661
extension BigInt: IntegerInitableWithRadix { }
5762

5863
extension BigUInt: IntegerInitableWithRadix { }
59-
// ------

Sources/web3swift/API/Web3+APIMethod.swift

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
//
77

88
import Foundation
9-
10-
public protocol APIResponseType: Decodable { }
9+
import BigInt
1110

1211
public typealias Hash = String // 32 bytes hash of block (64 chars length without 0x)
1312
public typealias Receipt = Hash
@@ -96,15 +95,17 @@ extension APIRequest {
9695
}
9796
}
9897

99-
public var responseType: APIResponseType.Type {
98+
public var responseType: APIResultType.Type {
10099
switch self {
101100
case .blockNumber: return UInt.self
101+
case .getAccounts: return [EthereumAddress].self
102+
case .feeHistory: return Web3.Oracle.FeeHistory.self
102103
default: return String.self
103104
}
104105
}
105106

106107
var encodedBody: Data {
107-
let request = RequestBody(method: self.call, parameters: self.parameters)
108+
let request = RequestBody(method: self.call, params: self.parameters)
108109
// this is safe to force try this here
109110
// Because request must failed to compile if it not conformable with `Encodable` protocol
110111
return try! JSONEncoder().encode(request)
@@ -142,7 +143,7 @@ extension APIRequest {
142143
case .getBlockByNumber(let hash, let bool):
143144
return [RequestParameter.string(hash), RequestParameter.bool(bool)]
144145
case .feeHistory(let uInt, let blockNumber, let array):
145-
return [RequestParameter.uint(uInt), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)]
146+
return [RequestParameter.string(uInt.hexString), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)]
146147
case .createAccount(let string):
147148
return [RequestParameter]()
148149
case .unlockAccount(let address, let string, let optional):
@@ -188,31 +189,35 @@ extension APIRequest {
188189
}
189190

190191
extension APIRequest {
191-
public static func sendRequest<U>(with call: APIRequest) async throws -> APIResponse<U> {
192-
/// Don't even try to make network request if the U type dosen't equal to supposed by API
192+
public static func sendRequest<Result>(with provider: Web3Provider, for call: APIRequest) async throws -> APIResponse<Result> {
193+
/// Don't even try to make network request if the `Result` type dosen't equal to supposed by API
193194
// FIXME: Add appropriate error thrown
194-
guard U.self == call.responseType else { throw Web3Error.unknownError }
195+
guard Result.self == call.responseType else { throw Web3Error.unknownError }
195196

196-
let request = setupRequest(for: call)
197-
let (data, response) = try await URLSession.shared.data(for: request)
197+
let request = setupRequest(for: call, with: provider)
198+
let (data, response) = try await provider.session.data(for: request)
198199

199200
// FIXME: Add appropriate error thrown
200201
guard let httpResponse = response as? HTTPURLResponse,
201202
200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError }
202203

203-
if U.self == UInt.self || U.self == Int.self || U.self == BigInt.self || U.self == BigUInt.self {
204-
let some = try! JSONDecoder().decode(APIResponse<String>.self, from: data)
204+
if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self {
205+
/// This types for sure conformed with `LiteralInitiableFromString`
206+
// FIXME: Make appropriate error
207+
guard let U = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.unknownError}
208+
let responseAsString = try! JSONDecoder().decode(APIResponse<String>.self, from: data)
205209
// FIXME: Add appropriate error thrown.
206-
guard let tmpAnother = U(from: some.result) else { throw Web3Error.unknownError }
207-
return APIResponse(id: some.id, jsonrpc: some.jsonrpc, result: tmpAnother)
210+
guard let literalValue = U.init(from: responseAsString.result) else { throw Web3Error.unknownError }
211+
/// `U` is a APIResponseType type, which `LiteralInitiableFromString` conforms to, so it is safe to cast that.
212+
// FIXME: Make appropriate error
213+
guard let asT = literalValue as? Result else { throw Web3Error.unknownError }
214+
return APIResponse(id: responseAsString.id, jsonrpc: responseAsString.jsonrpc, result: asT)
208215
}
209-
return try JSONDecoder().decode(APIResponse<U>.self, from: data)
216+
return try JSONDecoder().decode(APIResponse<Result>.self, from: data)
210217
}
211218

212-
static func setupRequest(for call: APIRequest) -> URLRequest {
213-
// FIXME: Make custom url
214-
let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")!
215-
var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData)
219+
static func setupRequest(for call: APIRequest, with provider: Web3Provider) -> URLRequest {
220+
var urlRequest = URLRequest(url: provider.url, cachePolicy: .reloadIgnoringCacheData)
216221
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
217222
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
218223
urlRequest.httpMethod = call.method.rawValue
@@ -226,17 +231,17 @@ public enum REST: String {
226231
case GET
227232
}
228233

229-
public struct RequestBody: Encodable {
234+
struct RequestBody: Encodable {
230235
var jsonrpc = "2.0"
231236
var id = Counter.increment()
232237

233238
var method: String
234-
var parameters: [RequestParameter]
239+
var params: [RequestParameter]
235240
}
236241

237242
/// JSON RPC response structure for serialization and deserialization purposes.
238-
public struct APIResponse<T>: Decodable where T: LiteralInitableFromString {
243+
public struct APIResponse<Result>: Decodable where Result: APIResultType {
239244
public var id: Int
240245
public var jsonrpc = "2.0"
241-
public var result: T
246+
public var result: Result
242247
}

Sources/web3swift/API/Web3+APIRequestParameter.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import Foundation
1212
/// Due to internal logic and swift itself restrictions, there's lack of encoding generic types
1313
/// so current implementation of `RequestParameter`s belongs on hardcoded supported types.
1414
///
15-
/// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request).
16-
///
1715
/// Please see `RequestParameter` documentation for more details.
1816
protocol APIRequestParameterType: Encodable { }
1917

0 commit comments

Comments
 (0)