Skip to content

Commit 8387947

Browse files
made common ws provider and specialized infura
1 parent e53e03b commit 8387947

File tree

2 files changed

+178
-70
lines changed

2 files changed

+178
-70
lines changed

web3swift/Web3/Classes/Web3+Methods.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,12 @@ public struct JSONRPCRequestFabric {
8383
request.params = pars
8484
return request
8585
}
86+
87+
public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [Encodable]) -> InfuraWebsocketRequest {
88+
var request = InfuraWebsocketRequest()
89+
request.method = method
90+
let pars = JSONRPCparams(params: parameters)
91+
request.params = pars
92+
return request
93+
}
8694
}

web3swift/Web3/Classes/Web3+WebsocketProvider.swift

Lines changed: 170 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,60 @@ import BigInt
1212
import Foundation
1313

1414
public protocol WebsocketProvider {
15-
var socket: WebSocket? {get set}
16-
var delegate: Web3SocketDelegate? {get set}
17-
static func connectToSocket(_ provider: Web3Provider, delegate: Web3SocketDelegate) -> Web3SocketProvider?
18-
func subscribeOn(method: WebsocketMethod, params: JSONRPCparams?) throws
15+
var socket: WebSocket {get}
16+
var delegate: Web3SocketDelegate {get set}
17+
static func connectToSocket(endpoint: URL,
18+
delegate: Web3SocketDelegate,
19+
keystoreManager manager: KeystoreManager?) -> Web3SocketProvider
20+
func connectSocket() throws
1921
func disconnectSocket() throws
2022
}
2123

22-
public enum WebsocketMethod {
23-
case pendingTransactions
24+
public enum InfuraWebsocketMethod: String, Encodable {
2425

25-
public var getJSONRPCmethod: JSONRPCmethod {
26-
switch self {
27-
case .pendingTransactions:
28-
return .newPendingTransactionFilter
26+
case newPendingTransactionFilter = "eth_newPendingTransactionFilter"
27+
case getFilterChanges = "eth_getFilterChanges"
28+
29+
public var requiredNumOfParameters: Int {
30+
get {
31+
switch self {
32+
case .newPendingTransactionFilter:
33+
return 0
34+
case .getFilterChanges:
35+
return 1
36+
}
37+
}
38+
}
39+
}
40+
41+
public struct InfuraWebsocketRequest: Encodable {
42+
public var jsonrpc: String = "2.0"
43+
public var method: InfuraWebsocketMethod?
44+
public var params: JSONRPCparams?
45+
public var id: UInt64 = Counter.increment()
46+
47+
enum CodingKeys: String, CodingKey {
48+
case jsonrpc
49+
case method
50+
case params
51+
case id
52+
}
53+
54+
public func encode(to encoder: Encoder) throws {
55+
var container = encoder.container(keyedBy: CodingKeys.self)
56+
try container.encode(jsonrpc, forKey: .jsonrpc)
57+
try container.encode(method?.rawValue, forKey: .method)
58+
try container.encode(params, forKey: .params)
59+
try container.encode(id, forKey: .id)
60+
}
61+
62+
public var isValid: Bool {
63+
get {
64+
if self.method == nil {
65+
return false
66+
}
67+
guard let method = self.method else {return false}
68+
return method.requiredNumOfParameters == self.params?.params.count
2969
}
3070
}
3171
}
@@ -34,57 +74,45 @@ public protocol Web3SocketDelegate {
3474
func received(message: Any)
3575
}
3676

37-
/// The default websocket provider.
38-
public class Web3SocketProvider: WebsocketProvider {
39-
40-
public var socket: WebSocket?
41-
public var delegate: Web3SocketDelegate?
77+
public final class InfuraWeb3SocketProvider: Web3SocketProvider {
4278
public var subscriptionKey: String?
43-
4479
private var subscriptionTimer: Timer?
4580

46-
private init() {}
47-
48-
public static func connectToSocket(_ provider: Web3Provider, delegate: Web3SocketDelegate) -> Web3SocketProvider? {
49-
let socketProvider = Web3SocketProvider()
50-
51-
guard let network = provider.network else {return nil}
81+
public init?(_ network: Networks,
82+
delegate: Web3SocketDelegate,
83+
keystoreManager manager: KeystoreManager?) {
5284
guard network == Networks.Kovan
5385
|| network == Networks.Rinkeby
5486
|| network == Networks.Ropsten
5587
|| network == Networks.Mainnet else {return nil}
5688
let networkName = network.name
5789
let urlString = "wss://\(networkName).infura.io/ws"
5890
guard let socketURL = URL(string: urlString) else {return nil}
59-
60-
socketProvider.socket = WebSocket(url: socketURL)
61-
socketProvider.socket?.delegate = socketProvider
62-
socketProvider.socket?.connect()
63-
socketProvider.delegate = delegate
64-
return socketProvider
91+
super.init(endpoint: socketURL,
92+
delegate: delegate,
93+
keystoreManager: manager)
6594
}
6695

67-
public func disconnectSocket() throws {
68-
guard let socket = self.socket else {
69-
throw Web3Error.connectionError
70-
}
71-
socket.disconnect()
96+
public static func connectToSocket(_ network: Networks,
97+
delegate: Web3SocketDelegate,
98+
keystoreManager manager: KeystoreManager?) -> Web3SocketProvider? {
99+
guard let socketProvider = InfuraWeb3SocketProvider(network,
100+
delegate: delegate,
101+
keystoreManager: manager) else {return nil}
102+
socketProvider.socket.connect()
103+
return socketProvider
72104
}
73105

74-
public func subscribeOn(method: WebsocketMethod, params: JSONRPCparams? = nil) throws {
106+
public func subscribeOn(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws {
75107
do {
76108
subscriptionTimer?.invalidate()
77-
guard let socket = self.socket else {
78-
throw Web3Error.connectionError
109+
subscriptionKey = nil
110+
let params = params ?? []
111+
let paramsCount = params.count
112+
guard method.requiredNumOfParameters == paramsCount else {
113+
throw Web3Error.inputError(desc: "Wrong number of params: need - \(method.requiredNumOfParameters), got - \(paramsCount)")
79114
}
80-
let jsonrpcMethod = method.getJSONRPCmethod
81-
let paramsCount = params == nil
82-
? 0
83-
: params!.params.count
84-
guard jsonrpcMethod.requiredNumOfParameters == paramsCount else {
85-
throw Web3Error.inputError(desc: "Wrong number of params: need - \(jsonrpcMethod.requiredNumOfParameters), got - \(paramsCount)")
86-
}
87-
let request = JSONRPCRequestFabric.prepareRequest(jsonrpcMethod, parameters: [])
115+
let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params)
88116
let encoder = JSONEncoder()
89117
let requestData = try encoder.encode(request)
90118
socket.write(data: requestData)
@@ -96,54 +124,126 @@ public class Web3SocketProvider: WebsocketProvider {
96124

97125
@objc public func getSubscriptionChanges() {
98126
DispatchQueue.global().async { [unowned self] in
99-
if let key = self.subscriptionKey,
100-
let socket = self.socket {
101-
// self.subscriptionTimer?.invalidate()
102-
// let method = JSONRPCmethod.getFilterChanges
103-
// let request = JSONRPCRequestFabric.prepareRequest(method, parameters: ["\(key)"])
104-
// let encoder = JSONEncoder()
105-
// if let requestData = try? encoder.encode(request) {
106-
// socket.write(data: requestData)
107-
// }
108-
109-
// TODO: - This should be in another way, but only this works
110-
socket.write(string: "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getFilterChanges\",\"params\":[\"\(key)\"],\"id\":1}")
127+
if let key = self.subscriptionKey {
111128
self.subscriptionTimer?.invalidate()
129+
let method = InfuraWebsocketMethod.getFilterChanges
130+
let request = JSONRPCRequestFabric.prepareRequest(method, parameters: [key])
131+
let encoder = JSONEncoder()
132+
if let requestData = try? encoder.encode(request) {
133+
self.socket.write(data: requestData)
134+
}
135+
136+
// // TODO: - This should be in another way, but only this works
137+
// self.socket.write(string: "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getFilterChanges\",\"params\":[\"\(key)\"],\"id\":1}")
138+
// self.subscriptionTimer?.invalidate()
112139
}
113140
}
114141
}
115-
}
116-
117-
extension Web3SocketProvider: WebSocketDelegate {
118-
public func websocketDidConnect(socket: WebSocketClient) {
119-
print("websocket is connected")
120-
}
121142

122-
public func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
123-
print("websocket is disconnected with \(error?.localizedDescription ?? "no error")")
124-
}
125-
126-
public func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
127-
print("got some text: \(text)")
143+
override public func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
128144
if let data = text.data(using: String.Encoding.utf8),
129145
let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] {
130146
if subscriptionKey == nil,
131147
let result = dictionary["result"] as? String {
132148
subscriptionKey = result
133149
} else {
134150
let result = dictionary["result"] as Any
135-
delegate?.received(message: result)
151+
delegate.received(message: result)
152+
}
153+
}
154+
}
155+
}
156+
157+
/// The default websocket provider.
158+
public class Web3SocketProvider: Web3Provider, WebsocketProvider, WebSocketDelegate {
159+
public func sendAsync(_ request: JSONRPCrequest, queue: DispatchQueue) -> Promise<JSONRPCresponse> {
160+
if request.method == nil {
161+
return Promise(error: Web3Error.nodeError(desc: "RPC method is nil"))
162+
}
163+
164+
return Web3HttpProvider.post(request, providerURL: self.url, queue: queue, session: self.session)
165+
}
166+
167+
public func sendAsync(_ requests: JSONRPCrequestBatch, queue: DispatchQueue) -> Promise<JSONRPCresponseBatch> {
168+
return Web3HttpProvider.post(requests, providerURL: self.url, queue: queue, session: self.session)
169+
}
170+
171+
public var network: Networks?
172+
public var url: URL
173+
public var session: URLSession = {() -> URLSession in
174+
let config = URLSessionConfiguration.default
175+
let urlSession = URLSession(configuration: config)
176+
return urlSession
177+
}()
178+
public var attachedKeystoreManager: KeystoreManager? = nil
179+
180+
public var socket: WebSocket
181+
public var delegate: Web3SocketDelegate
182+
183+
public init(endpoint: URL,
184+
delegate wsdelegate: Web3SocketDelegate,
185+
keystoreManager manager: KeystoreManager?,
186+
network net: Networks? = nil) {
187+
delegate = wsdelegate
188+
attachedKeystoreManager = manager
189+
url = endpoint
190+
socket = WebSocket(url: endpoint)
191+
socket.delegate = self
192+
if net == nil {
193+
let request = JSONRPCRequestFabric.prepareRequest(.getNetwork, parameters: [])
194+
195+
if let response = try? Web3HttpProvider.post(request,
196+
providerURL: endpoint,
197+
queue: DispatchQueue.global(qos: .userInteractive),
198+
session: session).wait(),
199+
response.error == nil,
200+
let result: String = response.getValue(),
201+
let intNetworkNumber = Int(result) {
202+
network = Networks.fromInt(intNetworkNumber)
136203
}
204+
} else {
205+
network = net
137206
}
138207
}
139208

209+
public func connectSocket() {
210+
socket.connect()
211+
}
212+
213+
public func disconnectSocket() {
214+
socket.disconnect()
215+
}
216+
217+
public static func connectToSocket(endpoint: URL,
218+
delegate: Web3SocketDelegate,
219+
keystoreManager manager: KeystoreManager?) -> Web3SocketProvider {
220+
let socketProvider = Web3SocketProvider(endpoint: endpoint,
221+
delegate: delegate,
222+
keystoreManager: manager)
223+
socketProvider.connectSocket()
224+
return socketProvider
225+
}
226+
227+
public func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
228+
print("got some text: \(text)")
229+
delegate.received(message: text)
230+
}
231+
140232
public func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
141233
print("got some data: \(data.count)")
234+
delegate.received(message: data)
235+
}
236+
237+
public func websocketDidConnect(socket: WebSocketClient) {
238+
print("websocket is connected")
239+
}
240+
241+
public func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
242+
print("websocket is disconnected with \(error?.localizedDescription ?? "no error")")
142243
}
143244

144245
public func websocketDidReceivePong(socket: WebSocketClient, data: Data?) {
145246
print("Got pong! Maybe some data: \(data?.count)")
146247
}
147248
}
148249

149-

0 commit comments

Comments
 (0)