Skip to content

Commit 88abb45

Browse files
Merge branch 'develop' into feature/gas-prediction
2 parents 9ac833b + c9b050a commit 88abb45

16 files changed

+412
-420
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242
run: sleep 1
4343
- name: Run local tests
4444
run: swift test --skip-build -c debug --filter localTests
45-
# - name: Run remote tests
46-
# run: swift test --skip-build -c debug --filter remoteTests
45+
- name: Run remote tests
46+
run: swift test --skip-build -c debug --filter remoteTests
4747
carthage:
4848
name: Carthage
4949
runs-on: macOS-11
@@ -64,7 +64,7 @@ jobs:
6464
- name: Building dependencies
6565
run: carthage build --no-use-binaries --platform iOS Simulator --use-xcframeworks
6666
- name: Building framework
67-
run: xcodebuild build-for-testing -project "web3swift.xcodeproj" -scheme "web3swift" -destination "${{matrix.destination}}" -testPlan LocalTests
67+
run: xcodebuild build-for-testing -project "web3swift.xcodeproj" -scheme "web3swift" -destination "${{matrix.destination}}"
6868
- name: Install ganache
6969
run: npm install ganache --global
7070
- name: Start ganache in background
@@ -73,5 +73,5 @@ jobs:
7373
run: sleep 1
7474
- name: Run local tests
7575
run: xcodebuild test-without-building -project "web3swift.xcodeproj" -scheme "web3swift" -destination "${{matrix.destination}}" -testPlan LocalTests
76-
# - name: Run remote tests
77-
# run: xcodebuild test-without-building -project "web3swift.xcodeproj" -scheme "web3swift" -destination "${{matrix.destination}}" -testPlan RemoteTests
76+
- name: Run remote tests
77+
run: xcodebuild test-without-building -project "web3swift.xcodeproj" -scheme "web3swift" -destination "${{matrix.destination}}" -testPlan RemoteTests

CONTRIBUTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Please take it from the [roadmap](https://hackmd.io/G5znP3xAQY-BVc1X8Y1jSg) or f
1818
## Codestyle guideline
1919
- `swiftlint` check should goes with no warnings.
2020
- Here’s some more detailed and human readable code style [guidelines](https://hackmd.io/8bACoAnTSsKc55Os596yCg "") (you can add there some suggestion if you’d like to).
21+
- We use [swift](https://www.swift.org/documentation/api-design-guidelines/ "") name convention.
2122
## Tests guideline
2223
1. Cover each new public method with tests.
2324
2. If you’re implementing some big feature encapsulate it in Separate file.

Sources/web3swift/Convenience/Decodable+Extensions.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,40 +106,44 @@ extension KeyedDecodingContainer {
106106
/// to be initialized as `BigUInt`.
107107
public func decodeHex<T: DecodableFromHex>(to type: T.Type, key: KeyedDecodingContainer<K>.Key) throws -> T {
108108
let string = try self.decode(String.self, forKey: key)
109-
guard let number = T(from: string) else { throw Web3Error.dataError }
109+
guard let number = T(fromHex: string) else { throw Web3Error.dataError }
110110
return number
111111
}
112112
}
113113

114114
public protocol DecodableFromHex: Decodable {
115-
init?(from hexString: String)
115+
init?(fromHex hexString: String)
116116
}
117117

118118
extension Data: DecodableFromHex {
119-
public init?(from hexString: String) {
119+
public init?(fromHex hexString: String) {
120120
self.init()
121121
guard let tmp = Self.fromHex(hexString) else { return nil }
122122
self = tmp
123123
}
124124
}
125125

126126
extension BigUInt: DecodableFromHex {
127-
public init?(from hexString: String) {
128-
self.init()
129-
guard let tmp = BigUInt(hexString.stripHexPrefix(), radix: 16) else { return nil }
130-
self = tmp
127+
public init?(fromHex hexString: String) {
128+
self.init(hexString.stripHexPrefix(), radix: 16)
131129
}
132130
}
133131

134132
extension Date: DecodableFromHex {
135-
public init?(from hexString: String) {
133+
public init?(fromHex hexString: String) {
136134
self.init()
137135
let stripedHexString = hexString.stripHexPrefix()
138136
guard let timestampInt = UInt64(stripedHexString, radix: 16) else { return nil }
139137
self = Date(timeIntervalSince1970: TimeInterval(timestampInt))
140138
}
141139
}
142140

141+
extension EthereumAddress: DecodableFromHex {
142+
public init?(fromHex hexString: String) {
143+
self.init(hexString, ignoreChecksum: true)
144+
}
145+
}
146+
143147
private extension KeyedDecodingContainer {
144148
func decode(_ type: [String: Any].Type) throws -> [String: Any] {
145149
var dictionary: [String: Any] = [:]

Sources/web3swift/Web3/Web3+EIP1559.swift

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public extension Web3 {
4444
/// - current: Current block
4545
/// - Returns: True or false if block is EIP-1559 or not
4646
static func isEip1559Block(parent: Block, current: Block) -> Bool {
47-
let parentGasLimit = parent.chainVersion >= .London ? parent.gasLimit : parent.gasLimit * Web3.ElasticityMultiplier
47+
let parentGasLimit = parent.mainChainVersion >= .London ? parent.gasLimit : parent.gasLimit * Web3.ElasticityMultiplier
4848

4949
guard verifyGasLimit(parentGasLimit: parentGasLimit, currentGasLimit: current.gasLimit) else { return false }
5050

@@ -60,39 +60,41 @@ public extension Web3 {
6060
///
6161
/// Calculation for current `Block` based on parents block object only
6262
///
63-
/// If passed block isn't `ChainVersion.London` one will return
63+
/// If passed block isn't `ChainVersion.London` nil will return
6464
///
6565
/// - Parameter parent: Parent `Block`
6666
/// - Returns: Amount of expected base fee for current `Block`
67-
static func calcBaseFee(_ parent: Block) -> BigUInt {
67+
static func calcBaseFee(_ parent: Block) -> BigUInt? {
68+
guard let parentBaseFee = parent.baseFeePerGas else { return nil }
69+
6870
// If given blocks ChainVersion is lower than London — always returns InitialBaseFee
69-
guard parent.chainVersion >= .London else { return Web3.InitialBaseFee }
71+
guard parent.mainChainVersion >= .London else { return Web3.InitialBaseFee }
7072

7173
let parentGasTarget = parent.gasLimit / Web3.ElasticityMultiplier
7274

7375
if parent.gasUsed > parentGasTarget {
7476
// If the parent block used more gas than its target, the baseFee should increase.
7577
let gasUsedDelta = parent.gasUsed - parentGasTarget
76-
let baseFeePerGasDelta = max(parent.baseFeePerGas * gasUsedDelta / parentGasTarget / Web3.BaseFeeChangeDenominator, 1)
77-
let expectedBaseFeePerGas = parent.baseFeePerGas + baseFeePerGasDelta
78+
let baseFeePerGasDelta = max(parentBaseFee * gasUsedDelta / parentGasTarget / Web3.BaseFeeChangeDenominator, 1)
79+
let expectedBaseFeePerGas = parentBaseFee + baseFeePerGasDelta
7880

7981
return expectedBaseFeePerGas
8082
} else if parent.gasUsed < parentGasTarget {
8183
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
8284
let gasUsedDelta = parentGasTarget - parent.gasUsed
83-
let baseFeePerGasDelta = parent.baseFeePerGas * gasUsedDelta / parentGasTarget / Web3.BaseFeeChangeDenominator
84-
let expectedBaseFeePerGas = parent.baseFeePerGas - baseFeePerGasDelta
85+
let baseFeePerGasDelta = parentBaseFee * gasUsedDelta / parentGasTarget / Web3.BaseFeeChangeDenominator
86+
let expectedBaseFeePerGas = parentBaseFee - baseFeePerGasDelta
8587

8688
return expectedBaseFeePerGas
8789
} else {
8890
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
89-
return parent.baseFeePerGas
91+
return parentBaseFee
9092
}
9193
}
9294
}
9395

9496
public extension Web3 {
95-
enum ChainVersion: BigUInt {
97+
enum MainChainVersion: BigUInt {
9698
/// Byzantium switch block
9799
///
98100
/// Date: 16.10.2017
@@ -149,29 +151,29 @@ public extension Web3 {
149151
}
150152
}
151153

152-
static func getChainVersion(of block: BigUInt) -> ChainVersion {
154+
static func getChainVersion(of block: BigUInt) -> MainChainVersion {
153155
// Iterate given block number over each ChainVersion block numbers
154156
// to get the block's ChainVersion.
155-
if block < ChainVersion.Constantinople.mainNetFisrtBlockNumber {
157+
if block < MainChainVersion.Constantinople.mainNetFisrtBlockNumber {
156158
return .Byzantium
157159
// ~= means included in a given range
158-
} else if ChainVersion.Constantinople.mainNetFisrtBlockNumber..<ChainVersion.Istanbul.mainNetFisrtBlockNumber ~= block {
160+
} else if MainChainVersion.Constantinople.mainNetFisrtBlockNumber..<MainChainVersion.Istanbul.mainNetFisrtBlockNumber ~= block {
159161
return .Constantinople
160-
} else if ChainVersion.Istanbul.mainNetFisrtBlockNumber..<ChainVersion.MuirGlacier.mainNetFisrtBlockNumber ~= block {
162+
} else if MainChainVersion.Istanbul.mainNetFisrtBlockNumber..<MainChainVersion.MuirGlacier.mainNetFisrtBlockNumber ~= block {
161163
return .Istanbul
162-
} else if ChainVersion.MuirGlacier.mainNetFisrtBlockNumber..<ChainVersion.Berlin.mainNetFisrtBlockNumber ~= block {
164+
} else if MainChainVersion.MuirGlacier.mainNetFisrtBlockNumber..<MainChainVersion.Berlin.mainNetFisrtBlockNumber ~= block {
163165
return .MuirGlacier
164-
} else if ChainVersion.Berlin.mainNetFisrtBlockNumber..<ChainVersion.London.mainNetFisrtBlockNumber ~= block {
166+
} else if MainChainVersion.Berlin.mainNetFisrtBlockNumber..<MainChainVersion.London.mainNetFisrtBlockNumber ~= block {
165167
return .Berlin
166-
} else if ChainVersion.London.mainNetFisrtBlockNumber..<ChainVersion.ArrowGlacier.mainNetFisrtBlockNumber ~= block {
168+
} else if MainChainVersion.London.mainNetFisrtBlockNumber..<MainChainVersion.ArrowGlacier.mainNetFisrtBlockNumber ~= block {
167169
return .London
168-
} else if block >= ChainVersion.ArrowGlacier.mainNetFisrtBlockNumber {
170+
} else if block >= MainChainVersion.ArrowGlacier.mainNetFisrtBlockNumber {
169171
// Pass to the default return.
170172
}
171173
return .ArrowGlacier
172174
}
173175
}
174176

175-
extension Web3.ChainVersion: Comparable {
176-
public static func < (lhs: Web3.ChainVersion, rhs: Web3.ChainVersion) -> Bool { return lhs.mainNetFisrtBlockNumber < rhs.mainNetFisrtBlockNumber }
177+
extension Web3.MainChainVersion: Comparable {
178+
public static func < (lhs: Web3.MainChainVersion, rhs: Web3.MainChainVersion) -> Bool { return lhs.mainNetFisrtBlockNumber < rhs.mainNetFisrtBlockNumber }
177179
}

Sources/web3swift/Web3/Web3+JSONRPC.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public struct JSONRPCresponse: Decodable{
109109
[String: Int].self,
110110
[String: [String: [String: [String]]]].self]
111111

112+
// FIXME: Make me a real generic
112113
public init(from decoder: Decoder) throws {
113114
let container = try decoder.container(keyedBy: JSONRPCresponseKeys.self)
114115
let id: Int = try container.decode(Int.self, forKey: .id)
@@ -163,24 +164,26 @@ public struct JSONRPCresponse: Decodable{
163164
self.init(id: id, jsonrpc: jsonrpc, result: result, error: nil)
164165
}
165166

167+
// FIXME: Make me a real generic
166168
/// Get the JSON RCP reponse value by deserializing it into some native <T> class.
167169
///
168170
/// Returns nil if serialization fails
169171
public func getValue<T>() -> T? {
170-
let slf = T.self
171-
if slf == BigUInt.self {
172+
let type = T.self
173+
174+
if type == BigUInt.self {
172175
guard let string = self.result as? String else {return nil}
173176
guard let value = BigUInt(string.stripHexPrefix(), radix: 16) else {return nil}
174177
return value as? T
175-
} else if slf == BigInt.self {
178+
} else if type == BigInt.self {
176179
guard let string = self.result as? String else {return nil}
177180
guard let value = BigInt(string.stripHexPrefix(), radix: 16) else {return nil}
178181
return value as? T
179-
} else if slf == Data.self {
182+
} else if type == Data.self {
180183
guard let string = self.result as? String else {return nil}
181184
guard let value = Data.fromHex(string) else {return nil}
182185
return value as? T
183-
} else if slf == EthereumAddress.self {
186+
} else if type == EthereumAddress.self {
184187
guard let string = self.result as? String else {return nil}
185188
guard let value = EthereumAddress(string, ignoreChecksum: true) else {return nil}
186189
return value as? T
@@ -192,25 +195,25 @@ public struct JSONRPCresponse: Decodable{
192195
// guard let value = self.result as? T else {return nil}
193196
// return value
194197
// }
195-
else if slf == [BigUInt].self {
198+
else if type == [BigUInt].self {
196199
guard let string = self.result as? [String] else {return nil}
197200
let values = string.compactMap { (str) -> BigUInt? in
198201
return BigUInt(str.stripHexPrefix(), radix: 16)
199202
}
200203
return values as? T
201-
} else if slf == [BigInt].self {
204+
} else if type == [BigInt].self {
202205
guard let string = self.result as? [String] else {return nil}
203206
let values = string.compactMap { (str) -> BigInt? in
204207
return BigInt(str.stripHexPrefix(), radix: 16)
205208
}
206209
return values as? T
207-
} else if slf == [Data].self {
210+
} else if type == [Data].self {
208211
guard let string = self.result as? [String] else {return nil}
209212
let values = string.compactMap { (str) -> Data? in
210213
return Data.fromHex(str)
211214
}
212215
return values as? T
213-
} else if slf == [EthereumAddress].self {
216+
} else if type == [EthereumAddress].self {
214217
guard let string = self.result as? [String] else {return nil}
215218
let values = string.compactMap { (str) -> EthereumAddress? in
216219
return EthereumAddress(str, ignoreChecksum: true)

Sources/web3swift/Web3/Web3+Structures.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public struct Block: Decodable {
339339
public var size: BigUInt
340340
public var gasLimit: BigUInt
341341
public var gasUsed: BigUInt
342-
public var baseFeePerGas: BigUInt
342+
public var baseFeePerGas: BigUInt?
343343
public var timestamp: Date
344344
public var transactions: [TransactionInBlock]
345345
public var uncles: [Data]
@@ -370,7 +370,7 @@ public struct Block: Decodable {
370370
}
371371

372372
/// Returns chain version of mainnet block with such number
373-
var chainVersion: Web3.ChainVersion { Web3.getChainVersion(of: number) }
373+
var mainChainVersion: Web3.MainChainVersion { Web3.getChainVersion(of: number) }
374374
}
375375

376376
extension Block {
@@ -401,7 +401,9 @@ extension Block {
401401
self.size = try container.decodeHex(to: BigUInt.self, key: .size)
402402
self.gasLimit = try container.decodeHex(to: BigUInt.self, key: .gasLimit)
403403
self.gasUsed = try container.decodeHex(to: BigUInt.self, key: .gasUsed)
404-
self.baseFeePerGas = try container.decodeHex(to: BigUInt.self, key: .baseFeePerGas)
404+
405+
// optional, since pre EIP-1559 block haven't such property.
406+
self.baseFeePerGas = try? container.decodeHex(to: BigUInt.self, key: .baseFeePerGas)
405407

406408
self.timestamp = try container.decodeHex(to: Date.self, key: .timestamp)
407409

Tests/web3swiftTests/localTests/EIP1559BlockTests.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ import web3swift
77
class EIP1559BlockTests: XCTestCase {
88
let uselessBlockPart = (
99
number: BigUInt(12_965_000),
10-
hash: Data(from: "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46")!, // "hash":
11-
parentHash: Data(from: "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88")!, // "parentHash":
12-
nonce: Data(from: "0xfb6e1a62d119228b"), // "nonce":
13-
sha3Uncles: Data(from: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "sha3Uncles":
14-
receiptsRoot: Data(from: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "receiptsRoot":
15-
logsBloom: EthereumBloomFilter(Data(from: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")!), // "logsBloom":
16-
transactionsRoot: Data(from: "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee")!, // "transactionsRoot":
17-
stateRoot: Data(from: "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb")!, // "stateRoot":
18-
miner: EthereumAddress( Data(from: "0x8888f1f195afa192cfee860698584c030f4c9db1")!)!, // "miner":
10+
hash: Data(fromHex: "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46")!, // "hash":
11+
parentHash: Data(fromHex: "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88")!, // "parentHash":
12+
nonce: Data(fromHex: "0xfb6e1a62d119228b"), // "nonce":
13+
sha3Uncles: Data(fromHex: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "sha3Uncles":
14+
receiptsRoot: Data(fromHex: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "receiptsRoot":
15+
logsBloom: EthereumBloomFilter(Data(fromHex: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")!), // "logsBloom":
16+
transactionsRoot: Data(fromHex: "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee")!, // "transactionsRoot":
17+
stateRoot: Data(fromHex: "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb")!, // "stateRoot":
18+
miner: EthereumAddress( Data(fromHex: "0x8888f1f195afa192cfee860698584c030f4c9db1")!)!, // "miner":
1919
difficulty: BigUInt(21345678965432), // "difficulty":
2020
totalDifficulty: BigUInt(324567845321), // "totalDifficulty":
2121
size: BigUInt(616), // "size":
22-
extraData: Data(from: "0x")!, // extraData":
22+
extraData: Data(fromHex: "0x")!, // extraData":
2323
gasLimit: BigUInt(3141592), // "gasLimit":
2424
gasUsed: BigUInt(21662), // "gasUsed":
2525
timestamp: Date(), // "timestamp":
@@ -145,7 +145,7 @@ class EIP1559BlockTests: XCTestCase {
145145

146146
let calculatedBaseFee = Web3.calcBaseFee(parent)
147147

148-
XCTAssertEqual(calculatedBaseFee, touple.expectedBaseFee, "Base fee calculation fails: should be \(touple.expectedBaseFee), got: \(calculatedBaseFee)")
148+
XCTAssertEqual(calculatedBaseFee, touple.expectedBaseFee, "Base fee calculation fails: should be \(touple.expectedBaseFee), got: \(String(describing: calculatedBaseFee))")
149149
}
150150
}
151151
}

Tests/web3swiftTests/localTests/LocalTests.xctestplan

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,11 @@
1414
"testTargets" : [
1515
{
1616
"skippedTests" : [
17-
"web3swiftENSTests",
18-
"web3swiftGanacheTests",
19-
"web3swiftRemoteParsingTests",
20-
"web3swiftST20AndSecurityTokenTests",
21-
"web3swiftWebsocketTests",
22-
"web3swift_ENS_Tests",
23-
"web3swift_ST20AndSecurityToken_Tests",
24-
"web3swift_infura_Tests",
25-
"web3swift_remoteParsing_Tests",
26-
"web3swift_websocket_Tests"
17+
"ENSTests",
18+
"RemoteTests",
19+
"RemoteParsingTests",
20+
"ST20AndSecurityTokenTests",
21+
"WebsocketTests",
2722
],
2823
"target" : {
2924
"containerPath" : "container:web3swift.xcodeproj",

0 commit comments

Comments
 (0)