Skip to content

Commit ee7e3d9

Browse files
committed
Merge branch 'develop' into remove-Promises
2 parents 544171e + c9b050a commit ee7e3d9

16 files changed

+503
-442
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: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Contribution guide
2+
## Version convention
3+
We’re conforming [default versions convention](https://semver.org/).
4+
So in the `1.0.0` version each position means follow:
5+
- 1.\*.***major release**, includes API groundbreaking changes (ie: your old code will not work).
6+
- \*.1.***minor release**, we’ve added some new feature to the lib, but we didn’t break something in anyway (ie: everything will work as expected without any moves after update).
7+
- \*.*.1 — **patch release**, we’re haven’t add any breaking changes or even new features for the user, but we’ve fixed some bugs or rewrote something internal (ie: you should not event mention that anything were changed in the lib).
8+
9+
This library yet living within **three weeks minor release** schedule. Also please keep in mind that in sake of avoiding complex merge conflicts, we’re currently taking only **one big feature** in release, so if you want to take some, please drop us a message somewhere to avoiding reworking it after it’ll be broken by some massive merge.
10+
11+
Critical bug fixes are should be marked with appropriate label in PR and should be proceed **within one week** till patch ’ll be released (at least we’ll try our best to made that).
12+
13+
## What task to choose
14+
Please take it from the [roadmap](https://hackmd.io/G5znP3xAQY-BVc1X8Y1jSg) or from the [opened issues](https://github.com/skywinder/web3swift/issues?q=is:issue+is:open+sort:updated-desc "").
15+
16+
> If you want to make something completely new and purely magical, please drop us a message somewhere before, since it could ends up that this is what we planning to do a lot later or that we not planning at all.
17+
18+
## Codestyle guideline
19+
- `swiftlint` check should goes with no warnings.
20+
- 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.
22+
## Tests guideline
23+
1. Cover each new public method with tests.
24+
2. If you’re implementing some big feature encapsulate it in Separate file.
25+
3. Choose one of the two directory to add test case:
26+
* `localTests` — tests which could be ran without needing to connecting to real Ethereum network.
27+
* `remoteTests` — tests which needing connection to real Ethereum network to be ran.
28+
4. Exclude added file from opposite `*.xctestplan` file (e.g. if you’re adding file to `localTests` please exclude it from `RemoteTests.xctestplan`.
29+
5. Add test file to `web3swift.xcodeproj` to make it working within Carthage building system.
30+
31+
## Hacks & tricks & magic
32+
### TestPlans
33+
In ci/cd we’re using Xcode test plans feature to spread tests to local and remote one. So any time you’re adding any new test suit (file) please exclude it from `LocalTests.xctestplan` rather `RemoteTests.xctestplan` depends on what tests group it included.
34+
### Swift package manager
35+
Please add any files unused due build process to `excludeFiles` array in `Package.swift`.
36+
### Carthage
37+
Please do not forget to add & remove all new or dropped files and dependencies in carthage `.xcodeproj` file if you’re working with project anywhere but carthage project.
38+
### Cocoapods
39+
Please do not forget to add & remove all dependencies within `web3swift.podspec` file.
40+
### GitHub actions
41+
You’re able to use our github actions checks in your fork without needing to make PR to this repo. To get that just add your branch name to the branch list in file on path `.github/actions/ci.yml` to let the magic happening like follow:
42+
43+
```yml
44+
on:
45+
push:
46+
branches:
47+
- master
48+
- develop
49+
- hotfix
50+
- #YOUR_REPO_NAME#
51+
```
52+
53+
> Please remove your branch from this list before making PR.
54+
55+
## Good PR checklist
56+
### Code
57+
- [ ] All new functionality covered by unit tests.
58+
- [ ] Ci/cd green.
59+
- [ ] No redundant files are added (build cache, Xcode breakpoints settings and so on).
60+
61+
### Info
62+
- [ ] Relative and concrete PR title.
63+
- [ ] Issue or roadmap goal attached.
64+
- [ ] PR description filled with detail explanation of what it is and what’s its specific.
65+
66+
### Codestyle
67+
- [ ] All public method have `///` styled comments.
68+
- [ ] All magic or nonintuitive internal code parts are clearly explained in inline comments.
69+
- [ ] `swiftlint` ran have no warnings.
70+
- [ ] No commented out code lefts in PR.

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

0 commit comments

Comments
 (0)