Skip to content

Commit cbca306

Browse files
committed
- Implement event loop. Should be started manually
1 parent 7f83ea2 commit cbca306

File tree

5 files changed

+149
-5
lines changed

5 files changed

+149
-5
lines changed

web3swift.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
81909D2F21885B2C007D2AE5 /* Web3+ERC721.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E94C5F217788E0005F54A0 /* Web3+ERC721.swift */; };
104104
81909D4A218864A8007D2AE5 /* EIP681.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A7B2862143DBF6004CD2C7 /* EIP681.swift */; };
105105
81909D4B218864A9007D2AE5 /* EIP681.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A7B2862143DBF6004CD2C7 /* EIP681.swift */; };
106+
81909D4F21887658007D2AE5 /* web3swift_Eventloop_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81909D4E21887658007D2AE5 /* web3swift_Eventloop_Tests.swift */; };
106107
81A1821520D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A1821420D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift */; };
107108
81A1821620D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A1821420D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift */; };
108109
81A1821A20D5A6F70016741F /* Promise+HttpProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A1821720D5A3E70016741F /* Promise+HttpProvider.swift */; };
@@ -262,6 +263,7 @@
262263
81909D1421862D37007D2AE5 /* Web3+MutatingTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+MutatingTransaction.swift"; sourceTree = "<group>"; };
263264
81909D1721862D5A007D2AE5 /* Web3+Eventloop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+Eventloop.swift"; sourceTree = "<group>"; };
264265
81909D2021884893007D2AE5 /* BigUInt+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BigUInt+Extensions.swift"; sourceTree = "<group>"; };
266+
81909D4E21887658007D2AE5 /* web3swift_Eventloop_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_Eventloop_Tests.swift; sourceTree = "<group>"; };
265267
81A1821420D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+Web3+Eth+GetBalance.swift"; sourceTree = "<group>"; };
266268
81A1821720D5A3E70016741F /* Promise+HttpProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+HttpProvider.swift"; sourceTree = "<group>"; };
267269
81A1821C20D5C6C10016741F /* web3swift_promises_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_promises_Tests.swift; sourceTree = "<group>"; };
@@ -424,6 +426,7 @@
424426
1CD91B301FD769A6007BFB45 /* web3swiftTests */ = {
425427
isa = PBXGroup;
426428
children = (
429+
81909D4E21887658007D2AE5 /* web3swift_Eventloop_Tests.swift */,
427430
1CB8188F2160867700726CF8 /* key.json */,
428431
81A7B2892143DF1D004CD2C7 /* web3swift_EIP681_Tests.swift */,
429432
81A7B2782143C978004CD2C7 /* web3swift_ENS_Tests.swift */,
@@ -1093,6 +1096,7 @@
10931096
81909D1F2187BD20007D2AE5 /* web3swift_numberFormattingUtil_Tests.swift in Sources */,
10941097
81909D1E2187BC8B007D2AE5 /* web3swift_transactions_Tests.swift in Sources */,
10951098
81909D2D218858EA007D2AE5 /* web3swift_ERC20_Class_Tests.swift in Sources */,
1099+
81909D4F21887658007D2AE5 /* web3swift_Eventloop_Tests.swift in Sources */,
10961100
);
10971101
runOnlyForDeploymentPostprocessing = 0;
10981102
};

web3swift/Web3/Classes/Web3+Eventloop.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,89 @@ import Foundation
88

99
extension web3.Eventloop {
1010

11+
// @available(iOS 10.0, *)
12+
public func start(_ timeInterval: TimeInterval) {
13+
if self.timer != nil {
14+
self.timer!.suspend()
15+
self.timer = nil
16+
}
17+
let queue = self.web3.requestDispatcher.queue
18+
queue.async {
19+
self.timer = RepeatingTimer(timeInterval: timeInterval)
20+
self.timer?.eventHandler = self.runnable
21+
self.timer?.resume()
22+
}
23+
}
24+
25+
public func stop() {
26+
if self.timer != nil {
27+
self.timer!.suspend()
28+
self.timer = nil
29+
}
30+
}
31+
32+
@objc func runnable() {
33+
for prop in self.monitoredProperties {
34+
let queue = prop.queue
35+
let function = prop.calledFunction
36+
queue.async {
37+
function(self.web3)
38+
}
39+
}
40+
}
41+
}
42+
43+
// Thank you https://medium.com/@danielgalasko/a-background-repeating-timer-in-swift-412cecfd2ef9
44+
class RepeatingTimer {
45+
46+
let timeInterval: TimeInterval
47+
48+
init(timeInterval: TimeInterval) {
49+
self.timeInterval = timeInterval
50+
}
51+
52+
private lazy var timer: DispatchSourceTimer = {
53+
let t = DispatchSource.makeTimerSource()
54+
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval)
55+
t.setEventHandler(handler: { [weak self] in
56+
self?.eventHandler?()
57+
})
58+
return t
59+
}()
60+
61+
var eventHandler: (() -> Void)?
62+
63+
private enum State {
64+
case suspended
65+
case resumed
66+
}
67+
68+
private var state: State = .suspended
69+
70+
deinit {
71+
timer.setEventHandler {}
72+
timer.cancel()
73+
/*
74+
If the timer is suspended, calling cancel without resuming
75+
triggers a crash. This is documented here https://forums.developer.apple.com/thread/15902
76+
*/
77+
resume()
78+
eventHandler = nil
79+
}
80+
81+
func resume() {
82+
if state == .resumed {
83+
return
84+
}
85+
state = .resumed
86+
timer.resume()
87+
}
88+
89+
func suspend() {
90+
if state == .suspended {
91+
return
92+
}
93+
state = .suspended
94+
timer.suspend()
95+
}
1196
}

web3swift/Web3/Classes/Web3+Instance.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,19 @@ public class web3: Web3OptionsInheritable {
166166
}
167167

168168
public class Eventloop: Web3OptionsInheritable {
169-
public typealias FunctionCall<T> = (web3) -> Result<T>
169+
public typealias EventLoopCall = (web3) -> Void
170170

171-
public struct MonitoredProperty<T> {
171+
public struct MonitoredProperty {
172172
public var name: String
173-
public var calledFunction: FunctionCall<T>
173+
public var queue: DispatchQueue
174+
public var calledFunction: EventLoopCall
174175
}
175176

176177
var provider:Web3Provider
177178
// weak var web3: web3?
178179
var web3: web3
179-
var timer: Promise<Void>?
180-
var monitoredProperties: [AnyObject] = [AnyObject]()
180+
var timer: RepeatingTimer? = nil
181+
var monitoredProperties: [MonitoredProperty] = [MonitoredProperty]()
181182
public var options: Web3Options {
182183
return self.web3.options
183184
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// web3swift
2+
//
3+
// Created by Alex Vlasov.
4+
// Copyright © 2018 Alex Vlasov. All rights reserved.
5+
//
6+
7+
import XCTest
8+
import EthereumAddress
9+
10+
@testable import web3swift_iOS
11+
12+
class web3swift_Eventloop_Tests: XCTestCase {
13+
14+
func testBasicEventLoop() {
15+
var ticksToWait = 10
16+
let expectation = self.expectation(description: "Waiting")
17+
func getBlockNumber(_ web3: web3) {
18+
do {
19+
let blockNumber = try web3.eth.getBlockNumber()
20+
print("Block number = " + String(blockNumber))
21+
ticksToWait = ticksToWait - 1
22+
if ticksToWait == 0 {
23+
expectation.fulfill()
24+
}
25+
} catch {
26+
print(error)
27+
}
28+
}
29+
let web3main = Web3.InfuraMainnetWeb3()
30+
let functionToCall: web3.Eventloop.EventLoopCall = getBlockNumber
31+
let monitoredProperty = web3.Eventloop.MonitoredProperty.init(name: "onNewBlock", queue: web3main.requestDispatcher.queue, calledFunction: functionToCall)
32+
web3main.eventLoop.monitoredProperties.append(monitoredProperty)
33+
web3main.eventLoop.start(1)
34+
35+
waitForExpectations(timeout: 30, handler: nil)
36+
}
37+
38+
}

web3swiftTests/web3swift_keystores_Tests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ class web3swift_Keystores_tests: XCTestCase {
4949
XCTAssertNotNil(key)
5050
}
5151

52+
func testV3keystoreSerialization() {
53+
let keystore = try! EthereumKeystoreV3(password: "");
54+
XCTAssertNotNil(keystore)
55+
let account = keystore!.addresses![0]
56+
let data = try! keystore!.serialize()
57+
let key = try! keystore!.UNSAFE_getPrivateKeyData(password: "", account: account)
58+
XCTAssertNotNil(key)
59+
60+
let restored = EthereumKeystoreV3(data!)
61+
XCTAssertNotNil(restored)
62+
XCTAssertEqual(keystore!.addresses!.first!, restored!.addresses!.first!)
63+
let restoredKey = try! restored!.UNSAFE_getPrivateKeyData(password: "", account: account)
64+
XCTAssertNotNil(restoredKey)
65+
XCTAssertEqual(key, restoredKey)
66+
}
67+
5268
func testNewBIP32keystore() {
5369
let mnemonic = try! BIP39.generateMnemonics(bitsOfEntropy: 256)!
5470
let keystore = try! BIP32Keystore(mnemonics: mnemonic, password: "", mnemonicsPassword: "")

0 commit comments

Comments
 (0)