Skip to content

Commit f03f816

Browse files
Merge pull request #514 from skywinder/feature/gas-prediction
Gas prediction implementation
2 parents c9b050a + c584da6 commit f03f816

File tree

10 files changed

+602
-116
lines changed

10 files changed

+602
-116
lines changed

Sources/web3swift/Convenience/Array+Extension.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//
66

77
import Foundation
8+
import BigInt
89

910
extension Array {
1011
public func split(intoChunksOf chunkSize: Int) -> [[Element]] {
@@ -14,3 +15,41 @@ extension Array {
1415
}
1516
}
1617
}
18+
19+
extension Array where Element: Comparable {
20+
/// Sorts array and drops most and least values.
21+
/// - Returns: Sorted array without most and least values, nil if `array.count` <= 2
22+
func cropAnomalyValues() -> Self? {
23+
var sortedArray = self.sorted()
24+
// Array should at least counts two to pass that formations.
25+
guard sortedArray.count > 1 else { return nil }
26+
sortedArray.removeLast()
27+
sortedArray.removeFirst()
28+
return sortedArray
29+
}
30+
}
31+
32+
extension Array where Element: BinaryInteger {
33+
// TODO: Make me generic
34+
/// Calculates mean value of a dataset
35+
/// - Returns: Mean value of a dataset, nil if dataset is empty
36+
func mean() -> BigUInt? {
37+
guard !self.isEmpty else { return nil }
38+
return BigUInt(self.reduce(0, +)) / BigUInt(self.count)
39+
}
40+
41+
42+
/// Calculates percentile of dataset on which get called.
43+
/// - Parameter value: Percentile value.
44+
/// - Returns: Item from dataset that is belongs to given percentile, nil if dataset is empty.
45+
func percentile(of value: Double) -> Element? {
46+
guard !self.isEmpty else { return nil }
47+
48+
let normalizedValue = value / 100 * Double(self.count)
49+
let index = Int(ceil(normalizedValue))
50+
51+
let sorted_data = self.sorted()
52+
guard index < self.count else { return sorted_data[sorted_data.endIndex] }
53+
return sorted_data[index]
54+
}
55+
}

Sources/web3swift/Convenience/Decodable+Extensions.swift

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extension KeyedDecodingContainer {
3535
/// for the given key.
3636
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for
3737
/// the given key.
38+
@available(*, deprecated, message: "Use decodeHex insetad")
3839
public func decode(_ type: [Any].Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> [Any] {
3940
var values = try nestedUnkeyedContainer(forKey: key)
4041
return try values.decode(type)
@@ -52,6 +53,7 @@ extension KeyedDecodingContainer {
5253
/// for the given key.
5354
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for
5455
/// the given key.
56+
@available(*, deprecated, message: "Use decodeHex() insetad")
5557
public func decode(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> [String: Any] {
5658
let values = try nestedContainer(keyedBy: AnyCodingKey.self, forKey: key)
5759
return try values.decode(type)
@@ -70,6 +72,7 @@ extension KeyedDecodingContainer {
7072
/// the value is a null value.
7173
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value
7274
/// is not convertible to the requested type.
75+
@available(*, deprecated, message: "In next version Will be replaced by decodeHexIfPresent() insetad")
7376
public func decodeIfPresent(_ type: [Any].Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> [Any]? {
7477
guard contains(key),
7578
try decodeNil(forKey: key) == false else { return nil }
@@ -89,26 +92,93 @@ extension KeyedDecodingContainer {
8992
/// the value is a null value.
9093
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value
9194
/// is not convertible to the requested type.
95+
@available(*, deprecated, message: "In next version Will be replaced by decodeHexIfPresent() insetad")
9296
public func decodeIfPresent(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> [String: Any]? {
9397
guard contains(key),
9498
try decodeNil(forKey: key) == false else { return nil }
9599
return try decode(type, forKey: key)
96100
}
97101

98-
/// Decodes a value of the given key from Hex to BigUInt
102+
/// Decodes a value of the given key from Hex to `DecodableFromHex`
99103
///
100104
/// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`
101105
///
102106
/// - Parameter type: Generic type `T` wich conforms to `DecodableFromHex` protocol
103107
/// - Parameter key: The key that the decoded value is associated with.
104108
/// - Returns: A decoded value of type `BigUInt`
105-
/// - throws: `Web3Error.dataError` if value associated with key are unable
106-
/// to be initialized as `BigUInt`.
107-
public func decodeHex<T: DecodableFromHex>(to type: T.Type, key: KeyedDecodingContainer<K>.Key) throws -> T {
108-
let string = try self.decode(String.self, forKey: key)
109-
guard let number = T(fromHex: string) else { throw Web3Error.dataError }
109+
/// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `DecodableFromHex`.
110+
public func decodeHex<T: DecodableFromHex>(_ type: T.Type, forKey: KeyedDecodingContainer<K>.Key) throws -> T {
111+
let hexString = try self.decode(String.self, forKey: forKey)
112+
guard let number = T(fromHex: hexString) else { throw Web3Error.dataError }
110113
return number
111114
}
115+
116+
/// Decodes a value of the given key from Hex to `[DecodableFromHex]`
117+
///
118+
/// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`
119+
///
120+
/// - Parameter type: Array of a generic type `T` wich conforms to `DecodableFromHex` protocol
121+
/// - Parameter key: The key that the decoded value is associated with.
122+
/// - Returns: A decoded value of type `BigUInt`
123+
/// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[[DecodableFromHex]]`.
124+
public func decodeHex<T: DecodableFromHex>(_ type: [T].Type, forKey: KeyedDecodingContainer<K>.Key) throws -> [T] {
125+
var container = try nestedUnkeyedContainer(forKey: forKey)
126+
guard let array = try? container.decodeHex(type) else { throw Web3Error.dataError }
127+
return array
128+
}
129+
130+
/// Decodes a value of the given key from Hex to `[DecodableFromHex]`
131+
///
132+
/// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`, `EthereumAddress`
133+
///
134+
/// - Parameter type: Array of a generic type `T` wich conforms to `DecodableFromHex` protocol
135+
/// - Parameter key: The key that the decoded value is associated with.
136+
/// - Returns: A decoded value of type `BigUInt`
137+
/// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[[DecodableFromHex]]`.
138+
public func decodeHex<T: DecodableFromHex>(_ type: [[T]].Type, forKey: KeyedDecodingContainer<K>.Key) throws -> [[T]] {
139+
var container = try nestedUnkeyedContainer(forKey: forKey)
140+
guard let array = try? container.decodeHex(type) else { throw Web3Error.dataError }
141+
return array
142+
}
143+
}
144+
145+
public extension UnkeyedDecodingContainer {
146+
/// Decodes a unkeyed value from hex to `[DecodableFromHex]`
147+
///
148+
/// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`, `EthereumAddress`
149+
///
150+
/// - Parameter type: Generic type `T` wich conforms to `DecodableFromHex` protocol
151+
/// - Parameter key: The key that the decoded value is associated with.
152+
/// - Returns: A decoded value of type `BigUInt`
153+
/// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[DecodableFromHex]`.
154+
mutating func decodeHex<T: DecodableFromHex>(_ type: [T].Type) throws -> [T] {
155+
var array: [T] = []
156+
while !isAtEnd {
157+
let hexString = try decode(String.self)
158+
guard let item = T(fromHex: hexString) else { continue }
159+
array.append(item)
160+
}
161+
return array
162+
}
163+
164+
165+
/// Decodes a unkeyed value from Hex to `DecodableFromHex`
166+
///
167+
/// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`, `EthereumAddress`
168+
///
169+
/// - Parameter type: Generic type `T` wich conforms to `DecodableFromHex` protocol
170+
/// - Parameter key: The key that the decoded value is associated with.
171+
/// - Returns: A decoded value of type `BigUInt`
172+
/// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[[DecodableFromHex]]`.
173+
mutating func decodeHex<T: DecodableFromHex>(_ type: [[T]].Type) throws -> [[T]] {
174+
var array: [[T]] = []
175+
while !isAtEnd {
176+
var container = try nestedUnkeyedContainer()
177+
let intArr = try container.decodeHex([T].self)
178+
array.append(intArr)
179+
}
180+
return array
181+
}
112182
}
113183

114184
public protocol DecodableFromHex: Decodable {
@@ -144,6 +214,7 @@ extension EthereumAddress: DecodableFromHex {
144214
}
145215
}
146216

217+
// deprecated, should be removed in 3.0.0
147218
private extension KeyedDecodingContainer {
148219
func decode(_ type: [String: Any].Type) throws -> [String: Any] {
149220
var dictionary: [String: Any] = [:]
@@ -168,6 +239,7 @@ private extension KeyedDecodingContainer {
168239
}
169240
}
170241

242+
// deprecated, should be removed in 3.0.0
171243
private extension UnkeyedDecodingContainer {
172244
mutating func decode(_ type: [Any].Type) throws -> [Any] {
173245
var elements: [Any] = []
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// Promise+Web3+Eth+FeeHistory.swift
3+
// web3swift
4+
//
5+
// Created by Yaroslav on 11.04.2022.
6+
// Copyright © 2022 web3swift. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import PromiseKit
11+
import BigInt
12+
13+
extension web3.Eth {
14+
func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) throws -> Web3.Oracle.FeeHistory {
15+
let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: [blockCount.description.addHexPrefix(), block, percentiles])
16+
let rp = web3.dispatch(request)
17+
let queue = web3.requestDispatcher.queue
18+
return try rp.map(on: queue) { response in
19+
guard let value: Web3.Oracle.FeeHistory = response.getValue() else {
20+
if response.error != nil {
21+
throw Web3Error.nodeError(desc: response.error!.message)
22+
}
23+
throw Web3Error.nodeError(desc: "Invalid value from Ethereum node")
24+
}
25+
return value
26+
}.wait()
27+
}
28+
}

0 commit comments

Comments
 (0)