From c53c4e43ec5b7cd3f69b11128847cb897127979f Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 28 Apr 2022 21:05:45 +0300 Subject: [PATCH 01/45] Delete untyped decode methods. --- .../Convenience/Decodable+Extensions.swift | 139 +----------------- .../remoteTests/GasOracleTests.swift | 4 - 2 files changed, 5 insertions(+), 138 deletions(-) diff --git a/Sources/web3swift/Convenience/Decodable+Extensions.swift b/Sources/web3swift/Convenience/Decodable+Extensions.swift index 0df9166c5..b42a0727d 100644 --- a/Sources/web3swift/Convenience/Decodable+Extensions.swift +++ b/Sources/web3swift/Convenience/Decodable+Extensions.swift @@ -23,82 +23,6 @@ struct AnyCodingKey: CodingKey { } extension KeyedDecodingContainer { - /// Decodes a value of the given type for the given key. - /// - /// - parameter type: The type of value to decode. - /// - parameter key: The key that the decoded value is associated with. - /// - returns: A value of the requested type, if present for the given key - /// and convertible to the requested type. - /// - throws: `DecodingError.typeMismatch` if the encountered encoded value - /// is not convertible to the requested type. - /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry - /// for the given key. - /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for - /// the given key. - @available(*, deprecated, message: "Use decodeHex insetad") - public func decode(_ type: [Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [Any] { - var values = try nestedUnkeyedContainer(forKey: key) - return try values.decode(type) - } - - /// Decodes a value of the given type for the given key. - /// - /// - parameter type: The type of value to decode. - /// - parameter key: The key that the decoded value is associated with. - /// - returns: A value of the requested type, if present for the given key - /// and convertible to the requested type. - /// - throws: `DecodingError.typeMismatch` if the encountered encoded value - /// is not convertible to the requested type. - /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry - /// for the given key. - /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for - /// the given key. - @available(*, deprecated, message: "Use decodeHex() insetad") - public func decode(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [String: Any] { - let values = try nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) - return try values.decode(type) - } - - /// Decodes a value of the given type for the given key, if present. - /// - /// This method returns `nil` if the container does not have a value - /// associated with `key`, or if the value is null. The difference between - /// these states can be distinguished with a `contains(_:)` call. - /// - /// - parameter type: The type of value to decode. - /// - parameter key: The key that the decoded value is associated with. - /// - returns: A decoded value of the requested type, or `nil` if the - /// `Decoder` does not have an entry associated with the given key, or if - /// the value is a null value. - /// - throws: `DecodingError.typeMismatch` if the encountered encoded value - /// is not convertible to the requested type. - @available(*, deprecated, message: "In next version Will be replaced by decodeHexIfPresent() insetad") - public func decodeIfPresent(_ type: [Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [Any]? { - guard contains(key), - try decodeNil(forKey: key) == false else { return nil } - return try decode(type, forKey: key) - } - - /// Decodes a value of the given type for the given key, if present. - /// - /// This method returns `nil` if the container does not have a value - /// associated with `key`, or if the value is null. The difference between - /// these states can be distinguished with a `contains(_:)` call. - /// - /// - parameter type: The type of value to decode. - /// - parameter key: The key that the decoded value is associated with. - /// - returns: A decoded value of the requested type, or `nil` if the - /// `Decoder` does not have an entry associated with the given key, or if - /// the value is a null value. - /// - throws: `DecodingError.typeMismatch` if the encountered encoded value - /// is not convertible to the requested type. - @available(*, deprecated, message: "In next version Will be replaced by decodeHexIfPresent() insetad") - public func decodeIfPresent(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [String: Any]? { - guard contains(key), - try decodeNil(forKey: key) == false else { return nil } - return try decode(type, forKey: key) - } - /// Decodes a value of the given key from Hex to `DecodableFromHex` /// /// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`, `UInt.Type` @@ -109,8 +33,8 @@ extension KeyedDecodingContainer { /// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `DecodableFromHex`. public func decodeHex(_ type: T.Type, forKey: KeyedDecodingContainer.Key) throws -> T { let hexString = try self.decode(String.self, forKey: forKey) - guard let number = T(fromHex: hexString) else { throw Web3Error.dataError } - return number + guard let value = T(fromHex: hexString) else { throw Web3Error.dataError } + return value } /// Decodes a value of the given key from Hex to `[DecodableFromHex]` @@ -119,7 +43,7 @@ extension KeyedDecodingContainer { /// /// - Parameter type: Array of a generic type `T` wich conforms to `DecodableFromHex` protocol /// - Parameter key: The key that the decoded value is associated with. - /// - Returns: A decoded value of type `T` + /// - Returns: A decoded value of type `[T]` /// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[[DecodableFromHex]]`. public func decodeHex(_ type: [T].Type, forKey: KeyedDecodingContainer.Key) throws -> [T] { var container = try nestedUnkeyedContainer(forKey: forKey) @@ -127,13 +51,13 @@ extension KeyedDecodingContainer { return array } - /// Decodes a value of the given key from Hex to `[DecodableFromHex]` + /// Decodes a value of the given key from Hex to `[[DecodableFromHex]]` /// /// Currently this method supports only `Data.Type`, `BigUInt.Type`, `Date.Type`, `EthereumAddress`, `UInt.Type` /// /// - Parameter type: Array of a generic type `T` wich conforms to `DecodableFromHex` protocol /// - Parameter key: The key that the decoded value is associated with. - /// - Returns: A decoded value of type `T` + /// - Returns: A decoded value of type `[[T]]` /// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `[[DecodableFromHex]]`. public func decodeHex(_ type: [[T]].Type, forKey: KeyedDecodingContainer.Key) throws -> [[T]] { var container = try nestedUnkeyedContainer(forKey: forKey) @@ -153,7 +77,6 @@ extension KeyedDecodingContainer { guard contains(forKey) else { return nil } return try decodeHex(type, forKey: forKey) } - } public extension UnkeyedDecodingContainer { @@ -233,55 +156,3 @@ extension EthereumAddress: DecodableFromHex { self.init(hexString, ignoreChecksum: true) } } - -// deprecated, should be removed in 3.0.0 -private extension KeyedDecodingContainer { - func decode(_ type: [String: Any].Type) throws -> [String: Any] { - var dictionary: [String: Any] = [:] - for key in allKeys { - if try decodeNil(forKey: key) { - dictionary[key.stringValue] = NSNull() - } else if let bool = try? decode(Bool.self, forKey: key) { - dictionary[key.stringValue] = bool - } else if let string = try? decode(String.self, forKey: key) { - dictionary[key.stringValue] = string - } else if let int = try? decode(Int.self, forKey: key) { - dictionary[key.stringValue] = int - } else if let double = try? decode(Double.self, forKey: key) { - dictionary[key.stringValue] = double - } else if let dict = try? decode([String: Any].self, forKey: key) { - dictionary[key.stringValue] = dict - } else if let array = try? decode([Any].self, forKey: key) { - dictionary[key.stringValue] = array - } - } - return dictionary - } -} - -// deprecated, should be removed in 3.0.0 -private extension UnkeyedDecodingContainer { - mutating func decode(_ type: [Any].Type) throws -> [Any] { - var elements: [Any] = [] - while !isAtEnd { - if try decodeNil() { - elements.append(NSNull()) - } else if let int = try? decode(Int.self) { - elements.append(int) - } else if let bool = try? decode(Bool.self) { - elements.append(bool) - } else if let double = try? decode(Double.self) { - elements.append(double) - } else if let string = try? decode(String.self) { - elements.append(string) - } else if let values = try? nestedContainer(keyedBy: AnyCodingKey.self), - let element = try? values.decode([String: Any].self) { - elements.append(element) - } else if var values = try? nestedUnkeyedContainer(), - let element = try? values.decode([Any].self) { - elements.append(element) - } - } - return elements - } -} diff --git a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift index f5ce2d70d..a236aa662 100644 --- a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift +++ b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift @@ -13,12 +13,8 @@ import BigInt // MARK: Works only with network connection class OracleTests: XCTestCase { - - let blockNumber: BigUInt = 14571792 - - func testPretictBaseFee() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) From e4012bf4c95476e7e0471715ced624f20571d94a Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 3 May 2022 18:27:05 +0300 Subject: [PATCH 02/45] Add generic encodeHex methods to `(Un)KeyedEncodingContainer` --- .../Convenience/Encodable+Extensions.swift | 133 ++++++++++-------- 1 file changed, 74 insertions(+), 59 deletions(-) diff --git a/Sources/web3swift/Convenience/Encodable+Extensions.swift b/Sources/web3swift/Convenience/Encodable+Extensions.swift index e6c39468f..8015a6c44 100644 --- a/Sources/web3swift/Convenience/Encodable+Extensions.swift +++ b/Sources/web3swift/Convenience/Encodable+Extensions.swift @@ -6,18 +6,19 @@ // Copyright © 2019 levantAJ. All rights reserved. // import Foundation +import BigInt -extension KeyedEncodingContainer { - /// Encodes the given value for the given key. - /// - /// - parameter value: The value to encode. - /// - parameter key: The key to associate the value with. - /// - throws: `EncodingError.invalidValue` if the given value is invalid in - /// the current context for this format. - public mutating func encode(_ value: [String: Any], forKey key: KeyedEncodingContainer.Key) throws { - var container = nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) - try container.encode(value) - } +public extension KeyedEncodingContainer { +// /// Encodes the given value for the given key. +// /// +// /// - parameter value: The value to encode. +// /// - parameter key: The key to associate the value with. +// /// - throws: `EncodingError.invalidValue` if the given value is invalid in +// /// the current context for this format. +// public mutating func encode(_ value: [String: Any], forKey key: KeyedEncodingContainer.Key) throws { +// var container = nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) +// try container.encode(value) +// } /// Encodes the given value for the given key. /// @@ -30,21 +31,31 @@ extension KeyedEncodingContainer { try container.encode(value) } - /// Encodes the given value for the given key if it is not `nil`. - /// - /// - parameter value: The value to encode. - /// - parameter key: The key to associate the value with. - /// - throws: `EncodingError.invalidValue` if the given value is invalid in - /// the current context for this format. - public mutating func encodeIfPresent(_ value: [String: Any]?, forKey key: KeyedEncodingContainer.Key) throws { - if let value = value { - var container = nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) - try container.encode(value) - } else { - try encodeNil(forKey: key) - } + + public mutating func encodeHex(_ value: T, forKey key: KeyedEncodingContainer.Key) throws { + try encode(value.hexString, forKey: key) + } + + public mutating func encodeHex(_ value: [T], forKey key: KeyedEncodingContainer.Key) throws { + var container = nestedUnkeyedContainer(forKey: key) + try container.encodeHex(value) } +// /// Encodes the given value for the given key if it is not `nil`. +// /// +// /// - parameter value: The value to encode. +// /// - parameter key: The key to associate the value with. +// /// - throws: `EncodingError.invalidValue` if the given value is invalid in +// /// the current context for this format. +// public mutating func encodeIfPresent(_ value: [String: Any]?, forKey key: KeyedEncodingContainer.Key) throws { +// if let value = value { +// var container = nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) +// try container.encode(value) +// } else { +// try encodeNil(forKey: key) +// } +// } + /// Encodes the given value for the given key if it is not `nil`. /// /// - parameter value: The value to encode. @@ -61,34 +72,25 @@ extension KeyedEncodingContainer { } } -private extension KeyedEncodingContainer where K == AnyCodingKey { - mutating func encode(_ value: [String: Any]) throws { - for (k, v) in value { - let key = AnyCodingKey(stringValue: k)! - switch v { - case is NSNull: - try encodeNil(forKey: key) - case let string as String: - try encode(string, forKey: key) - case let int as Int: - try encode(int, forKey: key) - case let bool as Bool: - try encode(bool, forKey: key) - case let double as Double: - try encode(double, forKey: key) - case let dict as [String: Any]: - try encode(dict, forKey: key) - case let array as [Any]: - try encode(array, forKey: key) - default: - debugPrint("⚠️ Unsuported type!", v) - continue +private extension UnkeyedEncodingContainer { + + public mutating func encodeHex(_ value: T) throws { + try encode(value.hexString) + } + + + mutating func encodeHex(_ value: [T]) throws { + try value.forEach { try encode($0.hexString) } + } + + mutating func encodeHex(_ value: [[T]]) throws { + try value.forEach { + try $0.forEach { + try encode($0.hexString) } } } -} -private extension UnkeyedEncodingContainer { /// Encodes the given value. /// /// - parameter value: The value to encode. @@ -107,8 +109,8 @@ private extension UnkeyedEncodingContainer { try encode(bool) case let double as Double: try encode(double) - case let dict as [String: Any]: - try encode(dict) +// case let dict as [String: Any]: +// try encode(dict) case let array as [Any]: var values = nestedUnkeyedContainer() try values.encode(array) @@ -118,13 +120,26 @@ private extension UnkeyedEncodingContainer { } } - /// Encodes the given value. - /// - /// - parameter value: The value to encode. - /// - throws: `EncodingError.invalidValue` if the given value is invalid in - /// the current context for this format. - mutating func encode(_ value: [String: Any]) throws { - var container = self.nestedContainer(keyedBy: AnyCodingKey.self) - try container.encode(value) - } +// /// Encodes the given value. +// /// +// /// - parameter value: The value to encode. +// /// - throws: `EncodingError.invalidValue` if the given value is invalid in +// /// the current context for this format. +// mutating func encode(_ value: [String: Any]) throws { +// var container = self.nestedContainer(keyedBy: AnyCodingKey.self) +// try container.encode(value) +// } } + + +public protocol EncodableToHex: Encodable { + var hexString: String { get } +} + +public extension EncodableToHex where Self: BinaryInteger { + var hexString: String { "0x" + String(self, radix: 16) } +} + +extension BigUInt: EncodableToHex { } + +extension UInt: EncodableToHex { } From d86583bdc7fe94689a9bbd7f261a1c6fa6fdc5a3 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 11 May 2022 00:04:27 +0700 Subject: [PATCH 03/45] Update `Encodable+Extensions` to be generic. --- .../Convenience/Encodable+Extensions.swift | 73 ++++--------------- 1 file changed, 16 insertions(+), 57 deletions(-) diff --git a/Sources/web3swift/Convenience/Encodable+Extensions.swift b/Sources/web3swift/Convenience/Encodable+Extensions.swift index 8015a6c44..a2780797e 100644 --- a/Sources/web3swift/Convenience/Encodable+Extensions.swift +++ b/Sources/web3swift/Convenience/Encodable+Extensions.swift @@ -8,7 +8,7 @@ import Foundation import BigInt -public extension KeyedEncodingContainer { +extension KeyedEncodingContainer { // /// Encodes the given value for the given key. // /// // /// - parameter value: The value to encode. @@ -20,23 +20,23 @@ public extension KeyedEncodingContainer { // try container.encode(value) // } - /// Encodes the given value for the given key. - /// - /// - parameter value: The value to encode. - /// - parameter key: The key to associate the value with. - /// - throws: `EncodingError.invalidValue` if the given value is invalid in - /// the current context for this format. - public mutating func encode(_ value: [Any], forKey key: KeyedEncodingContainer.Key) throws { - var container = nestedUnkeyedContainer(forKey: key) - try container.encode(value) - } +// /// Encodes the given value for the given key. +// /// +// /// - parameter value: The value to encode. +// /// - parameter key: The key to associate the value with. +// /// - throws: `EncodingError.invalidValue` if the given value is invalid in +// /// the current context for this format. +// public mutating func encode(_ value: [Any], forKey key: KeyedEncodingContainer.Key) throws { +// var container = nestedUnkeyedContainer(forKey: key) +// try container.encode(value) +// } - public mutating func encodeHex(_ value: T, forKey key: KeyedEncodingContainer.Key) throws { + mutating func encodeHex(_ value: T, forKey key: KeyedEncodingContainer.Key) throws { try encode(value.hexString, forKey: key) } - public mutating func encodeHex(_ value: [T], forKey key: KeyedEncodingContainer.Key) throws { + mutating func encodeHex(_ value: [T], forKey key: KeyedEncodingContainer.Key) throws { var container = nestedUnkeyedContainer(forKey: key) try container.encodeHex(value) } @@ -62,7 +62,7 @@ public extension KeyedEncodingContainer { /// - parameter key: The key to associate the value with. /// - throws: `EncodingError.invalidValue` if the given value is invalid in /// the current context for this format. - public mutating func encodeIfPresent(_ value: [Any]?, forKey key: KeyedEncodingContainer.Key) throws { + mutating func encodeIfPresent(_ value: [T]?, forKey key: KeyedEncodingContainer.Key) throws { if let value = value { var container = nestedUnkeyedContainer(forKey: key) try container.encode(value) @@ -72,13 +72,11 @@ public extension KeyedEncodingContainer { } } -private extension UnkeyedEncodingContainer { - - public mutating func encodeHex(_ value: T) throws { +extension UnkeyedEncodingContainer { + mutating func encodeHex(_ value: T) throws { try encode(value.hexString) } - mutating func encodeHex(_ value: [T]) throws { try value.forEach { try encode($0.hexString) } } @@ -90,45 +88,6 @@ private extension UnkeyedEncodingContainer { } } } - - /// Encodes the given value. - /// - /// - parameter value: The value to encode. - /// - throws: `EncodingError.invalidValue` if the given value is invalid in - /// the current context for this format. - mutating func encode(_ value: [Any]) throws { - for v in value { - switch v { - case is NSNull: - try encodeNil() - case let string as String: - try encode(string) - case let int as Int: - try encode(int) - case let bool as Bool: - try encode(bool) - case let double as Double: - try encode(double) -// case let dict as [String: Any]: -// try encode(dict) - case let array as [Any]: - var values = nestedUnkeyedContainer() - try values.encode(array) - default: - debugPrint("⚠️ Unsuported type!", v) - } - } - } - -// /// Encodes the given value. -// /// -// /// - parameter value: The value to encode. -// /// - throws: `EncodingError.invalidValue` if the given value is invalid in -// /// the current context for this format. -// mutating func encode(_ value: [String: Any]) throws { -// var container = self.nestedContainer(keyedBy: AnyCodingKey.self) -// try container.encode(value) -// } } From 24dc3a854365f28450dfe3229cae268ce76dbd19 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 13 May 2022 19:31:23 +0700 Subject: [PATCH 04/45] Making memos to methods. --- Sources/web3swift/Web3/Web3+JSONRPC.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index d7259f440..aec9e670a 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -122,7 +122,15 @@ public struct JSONRPCresponse: Decodable{ self.init(id: id, jsonrpc: jsonrpc, result: nil, error: errorMessage) return } - // TODO: refactor me + // TODO: make me generic (DecodableFromHex or Decodable) + /// This is all available types of `result` to init + /// Now its type is `Any?`, since you're typecasting this any to exact each response, + /// coz you're knowing response to what request it would be, + /// and you're could be sure about API Response structure. + /// + /// So since we're typecasting this explicitly each tyme, `result` property could be set + /// to protocol type like `Decodable` or `DevodableFromHex` or something, + /// and this code could be reduced so hard. var result: Any? = nil if let rawValue = try? container.decodeIfPresent(String.self, forKey: .result) { result = rawValue @@ -171,6 +179,7 @@ public struct JSONRPCresponse: Decodable{ } // FIXME: Make me a real generic + // MARK: - This fits for DecodableFromHex /// Get the JSON RCP reponse value by deserializing it into some native class. /// /// Returns nil if serialization fails @@ -281,6 +290,7 @@ public struct JSONRPCparams: Encodable{ // TODO: Rewrite me to generic public var params = [Any]() + // FIXME: Make me generic with encodableToHex (watch out bool) public func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() for par in params { From cd751ee776b84879818de1ac7a7787f67aa41e4d Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 14 May 2022 17:44:59 +0700 Subject: [PATCH 05/45] `JSONRPCParam` enum implementation. Enum to compose request to the node params. In most cases request params are passed to Ethereum JSON RPC request as array of mixed type values, such as `[12,"this",true]`, thus this is not appropriate API design we have what we have. Meanwhile swift don't provide strict way to compose such array it gives some hacks to solve this task and one of them is using `RawRepresentable` protocol. Conforming this protocol gives designated type ability to represent itself in `String` representation in any way. So in our case we're using such to implement custom `encode` method to any used in node request params types. --- Sources/web3swift/Web3/Web3+JSONRPC.swift | 139 ++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index aec9e670a..84ac6e1e9 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -22,6 +22,7 @@ public struct Counter { } /// JSON RPC request structure for serialization and deserialization purposes. +//public struct JSONRPCrequest: Encodable { public struct JSONRPCrequest: Encodable { public var jsonrpc: String = "2.0" public var method: JSONRPCmethod? @@ -291,6 +292,8 @@ public struct JSONRPCparams: Encodable{ public var params = [Any]() // FIXME: Make me generic with encodableToHex (watch out bool) + /// This method is encoding all possible params of a Ethereum JSON RPC request. + /// So type of this struct public func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() for par in params { @@ -308,3 +311,139 @@ public struct JSONRPCparams: Encodable{ } } } + +/** + Enum to compose request to the node params. + + In most cases request params are passed to Ethereum JSON RPC request as array of mixed type values, such as `[12,"this",true]`, + thus this is not appropriate API design we have what we have. + + Meanwhile swift don't provide strict way to compose such array it gives some hacks to solve this task + and one of them is using `RawRepresentable` protocol. + + Conforming this protocol gives designated type ability to represent itself in `String` representation in any way. + + So in our case we're using such to implement custom `encode` method to any used in node request params types. + + Latter is required to encode array of `JSONRPCParam` to not to `[JSONRPCParam.int(1)]`, but to `[1]`. + + Here's an example of using this enum in field. + ```swift + let jsonRPCParams: [JSONRPCParam] = [ + .init(rawValue: 12)!, + .init(rawValue: "this")!, + .init(rawValue: 12.2)!, + .init(rawValue: [12.2, 12.4])! + ] + let encoded = try JSONEncoder().encode(jsonRPCParams) + print(String(data: encoded, encoding: .utf8)!) + //> [12,\"this\",12.2,[12.2,12.4]]` + ``` + */ +public enum JSONRPCParam { + case int(Int) + case intArray([Int]) + + case double(Double) + case doubleArray([Double]) + + case string(String) + case stringArray([String]) + + case bool(Bool) + case transaction(TransactionParameters) + case eventFilter(EventFilterParameters) +} + +extension JSONRPCParam: RawRepresentable { + /** + This init required by `RawRepresentable` protocol, which is requred bo encode mixed type values array in JSON. + + This protocol used to implement custom `encode` method for that enum, + which is encodes array of self into array of self assotiated values. + + You're totally free to use explicit and more convenience member init as `JSONRPCParam.int(12)` in your code. + */ + public init?(rawValue: Encodable) { + /// force casting in this switch is safe because + /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type + // swiftlint:disable force_cast + switch type(of: rawValue) { + case is Int.Type: self = .int(rawValue as! Int) + case is [Int].Type: self = .intArray(rawValue as! [Int]) + + case is String.Type: self = .string(rawValue as! String) + case is [String].Type: self = .stringArray(rawValue as! [String]) + + case is Double.Type: self = .double(rawValue as! Double) + case is [Double].Type: self = .doubleArray(rawValue as! [Double]) + + case is Bool.Type: self = .bool(rawValue as! Bool) + case is TransactionParameters.Type: self = .transaction(rawValue as! TransactionParameters) + case is EventFilterParameters.Type: self = .eventFilter(rawValue as! EventFilterParameters) + default: return nil + } + // swiftlint:enable force_cast + } + + /// Returning associated value of the enum case only. + public var rawValue: Encodable { + // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. + switch self { + case let .int(value): return value + case let .intArray(value): return value + + case let .string(value): return value + case let .stringArray(value): return value + + case let .double(value): return value + case let .doubleArray(value): return value + + case let .bool(value): return value + case let .transaction(value): return value + case let .eventFilter(value): return value + } + } +} + +extension JSONRPCParam: Encodable { + /** + This encoder encodes `JSONRPCParam` assotiated value ignoring self value + + This is required to encode mixed types array, like + + ```swift + let someArray: [JSONRPCParam] = [ + .init(rawValue: 12)!, + .init(rawValue: "this")!, + .init(rawValue: 12.2)!, + .init(rawValue: [12.2, 12.4])! + ] + let encoded = try JSONEncoder().encode(someArray) + print(String(data: encoded, encoding: .utf8)!) + //> [12,\"this\",12.2,[12.2,12.4]]` + ``` + */ + public func encode(to encoder: Encoder) throws { + var enumContainer = encoder.singleValueContainer() + /// force casting in this switch is safe because + /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type + // swiftlint:disable force_cast + switch type(of: self.rawValue) { + case is Int.Type: try enumContainer.encode(rawValue as! Int) + case is [Int].Type: try enumContainer.encode(rawValue as! [Int]) + + case is String.Type: try enumContainer.encode(rawValue as! String) + case is [String].Type: try enumContainer.encode(rawValue as! [String]) + + case is Double.Type: try enumContainer.encode(rawValue as! Double) + case is [Double].Type: try enumContainer.encode(rawValue as! [Double]) + + case is Bool.Type: try enumContainer.encode(rawValue as! Bool) + case is TransactionParameters.Type: try enumContainer.encode(rawValue as! TransactionParameters) + case is EventFilterParameters.Type: try enumContainer.encode(rawValue as! EventFilterParameters) + default: break + } + // swiftlint:enable force_cast + } +} From fb4c10dc01506208a499497b57014c09815fed55 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 15 May 2022 16:57:09 +0700 Subject: [PATCH 06/45] `JSONRPCparams` replaced with `[JSONRPCParameter]` in outgoing API calls to Eth node. `prepareRequest` still takes `[Encodable]` as parameter argument and maps it to the `[JSONRPCParameter]`. All network tests pass well. --- .../Transaction/EthereumTransaction.swift | 14 +++-- Sources/web3swift/Web3/Web3+JSONRPC.swift | 51 +++++-------------- Sources/web3swift/Web3/Web3+Methods.swift | 6 +-- .../Web3/Web3+WebsocketProvider.swift | 4 +- 4 files changed, 23 insertions(+), 52 deletions(-) diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/web3swift/Transaction/EthereumTransaction.swift index 3c90172d4..336433f67 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/web3swift/Transaction/EthereumTransaction.swift @@ -193,12 +193,11 @@ public struct EthereumTransaction: CustomStringConvertible { if method == .estimateGas || transactionOptions?.gasLimit == nil { txParams.gas = nil } - var params = [txParams] as [Encodable] - if method.requiredNumOfParameters == 2 && onBlock != nil { - params.append(onBlock as Encodable) + var params: [JSONRPCParameter] = [.transaction(txParams)] + if let onBlock = onBlock, method.requiredNumOfParameters == 2 { + params.append(.string(onBlock)) } - let pars = JSONRPCparams(params: params) - request.params = pars + request.params = params if !request.isValid { return nil } return request } @@ -217,9 +216,8 @@ public struct EthereumTransaction: CustomStringConvertible { let hex = encodedData.toHexString().addHexPrefix().lowercased() var request = JSONRPCrequest() request.method = JSONRPCmethod.sendRawTransaction - let params = [hex] as [Encodable] - let pars = JSONRPCparams(params: params) - request.params = pars + let params: [JSONRPCParameter] = [.string(hex)] + request.params = params if !request.isValid { return nil } return request } diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index 84ac6e1e9..adaa68e6c 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -26,7 +26,7 @@ public struct Counter { public struct JSONRPCrequest: Encodable { public var jsonrpc: String = "2.0" public var method: JSONRPCmethod? - public var params: JSONRPCparams? + public var params: [JSONRPCParameter] = [] public var id: UInt64 = Counter.increment() enum CodingKeys: String, CodingKey { @@ -50,7 +50,7 @@ public struct JSONRPCrequest: Encodable { return false } guard let method = self.method else {return false} - return method.requiredNumOfParameters == self.params?.params.count + return method.requiredNumOfParameters == self.params.count } } } @@ -286,32 +286,6 @@ public struct EventFilterParameters: Codable { public var address: [String?]? } -/// Raw JSON RCP 2.0 internal flattening wrapper. -public struct JSONRPCparams: Encodable{ - // TODO: Rewrite me to generic - public var params = [Any]() - - // FIXME: Make me generic with encodableToHex (watch out bool) - /// This method is encoding all possible params of a Ethereum JSON RPC request. - /// So type of this struct - public func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - for par in params { - if let p = par as? TransactionParameters { - try container.encode(p) - } else if let p = par as? String { - try container.encode(p) - } else if let p = par as? Bool { - try container.encode(p) - } else if let p = par as? EventFilterParameters { - try container.encode(p) - } else if let p = par as? [Double] { - try container.encode(p) - } - } - } -} - /** Enum to compose request to the node params. @@ -325,11 +299,11 @@ public struct JSONRPCparams: Encodable{ So in our case we're using such to implement custom `encode` method to any used in node request params types. - Latter is required to encode array of `JSONRPCParam` to not to `[JSONRPCParam.int(1)]`, but to `[1]`. + Latter is required to encode array of `JSONRPCParameter` to not to `[JSONRPCParameter.int(1)]`, but to `[1]`. Here's an example of using this enum in field. ```swift - let jsonRPCParams: [JSONRPCParam] = [ + let jsonRPCParams: [JSONRPCParameter] = [ .init(rawValue: 12)!, .init(rawValue: "this")!, .init(rawValue: 12.2)!, @@ -340,7 +314,7 @@ public struct JSONRPCparams: Encodable{ //> [12,\"this\",12.2,[12.2,12.4]]` ``` */ -public enum JSONRPCParam { +public enum JSONRPCParameter { case int(Int) case intArray([Int]) @@ -355,14 +329,15 @@ public enum JSONRPCParam { case eventFilter(EventFilterParameters) } -extension JSONRPCParam: RawRepresentable { + +extension JSONRPCParameter: RawRepresentable { /** - This init required by `RawRepresentable` protocol, which is requred bo encode mixed type values array in JSON. + This init required by `RawRepresentable` protocol, which is requred to encode mixed type values array in JSON. This protocol used to implement custom `encode` method for that enum, which is encodes array of self into array of self assotiated values. - You're totally free to use explicit and more convenience member init as `JSONRPCParam.int(12)` in your code. + You're totally free to use explicit and more convenience member init as `JSONRPCParameter.int(12)` in your code. */ public init?(rawValue: Encodable) { /// force casting in this switch is safe because @@ -406,14 +381,14 @@ extension JSONRPCParam: RawRepresentable { } } -extension JSONRPCParam: Encodable { +extension JSONRPCParameter: Encodable { /** - This encoder encodes `JSONRPCParam` assotiated value ignoring self value + This encoder encodes `JSONRPCParameter` assotiated value ignoring self value This is required to encode mixed types array, like ```swift - let someArray: [JSONRPCParam] = [ + let someArray: [JSONRPCParameter] = [ .init(rawValue: 12)!, .init(rawValue: "this")!, .init(rawValue: 12.2)!, @@ -427,7 +402,7 @@ extension JSONRPCParam: Encodable { public func encode(to encoder: Encoder) throws { var enumContainer = encoder.singleValueContainer() /// force casting in this switch is safe because - /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type + /// each `rawValue` forced to casts only in exact case which is runs based on `rawValue` type // swiftlint:disable force_cast switch type(of: self.rawValue) { case is Int.Type: try enumContainer.encode(rawValue as! Int) diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index 9fe88aaab..d662d3726 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -78,16 +78,14 @@ public struct JSONRPCRequestFabric { public static func prepareRequest(_ method: JSONRPCmethod, parameters: [Encodable]) -> JSONRPCrequest { var request = JSONRPCrequest() request.method = method - let pars = JSONRPCparams(params: parameters) - request.params = pars + request.params = parameters.compactMap { JSONRPCParameter.init(rawValue: $0) } return request } public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [Encodable]) -> InfuraWebsocketRequest { var request = InfuraWebsocketRequest() request.method = method - let pars = JSONRPCparams(params: parameters) - request.params = pars + request.params = parameters.compactMap { JSONRPCParameter.init(rawValue: $0) } return request } } diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index f229a0f2d..bb22d485e 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -56,7 +56,7 @@ public enum InfuraWebsocketMethod: String, Encodable { public struct InfuraWebsocketRequest: Encodable { public var jsonrpc: String = "2.0" public var method: InfuraWebsocketMethod? - public var params: JSONRPCparams? + public var params: [JSONRPCParameter] = [] public var id: UInt64 = Counter.increment() enum CodingKeys: String, CodingKey { @@ -80,7 +80,7 @@ public struct InfuraWebsocketRequest: Encodable { return false } guard let method = self.method else {return false} - return method.requiredNumOfParameters == self.params?.params.count + return method.requiredNumOfParameters == self.params.count } } } From 88c84bbf87a8943551f75e2f15b46fa86918ee95 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 17 May 2022 16:42:48 +0700 Subject: [PATCH 07/45] To create `JSONRPCrequest` parameters should conforms `JSONRPCParameter` protocol. Also there's added `RPCParameter` enum which implements internal encoding logic of value of any conformed `JSONRPCParameter` type. Unfortunately there's no way in swift yet to encode generic types. Therefore there's no way to made both `JSONRPCParameter` & `RPCParameter` types extendable. So yet there's a manual restriction for supported types, **must** conforms rather `JSONRPCParameter` protocol for base types, and `JSONParameterElement` protocol for types that are stored in arrays. The latter protocol is internal to deny conforming to it by a library user. `JSONRPCParameter` itself could be one to conform with by a user custom type, since there's a lack of making this type internal due to `RawRepresentable` protocol restrictions. So there's nothing we can do, but a leaving a documentation with denying to do this. --- .../Promise+Web3+Eth+FeeHistory.swift | 5 +- .../Promise+Web3+Personal+UnlockAccount.swift | 4 +- .../Transaction/EthereumTransaction.swift | 4 +- .../web3swift/Web3/Web3+InfuraProviders.swift | 8 +- Sources/web3swift/Web3/Web3+JSONRPC.swift | 76 ++++++++++++++++--- Sources/web3swift/Web3/Web3+Methods.swift | 8 +- .../Web3/Web3+WebsocketProvider.swift | 2 +- 7 files changed, 82 insertions(+), 25 deletions(-) diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index 04c7a6353..dc3dd480d 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -11,7 +11,10 @@ import BigInt extension web3.Eth { func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { - let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: [blockCount.description.addHexPrefix(), block, percentiles]) + + let parameters: [JSONRPCParameter] = [blockCount.description.addHexPrefix(), block, percentiles] + + let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: parameters) let response = try await web3.dispatch(request) guard let value: Web3.Oracle.FeeHistory = response.getValue() else { diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift index 39cae095e..7a4e5f546 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift @@ -20,7 +20,9 @@ extension web3.Personal { throw Web3Error.inputError(desc: "Can not unlock a local keystore") } - let request = JSONRPCRequestFabric.prepareRequest(.unlockAccount, parameters: [account.lowercased(), password, seconds]) + let parameters: [JSONRPCParameter] = [account.lowercased(), password, seconds] + + let request = JSONRPCRequestFabric.prepareRequest(.unlockAccount, parameters: parameters) let response = try await self.web3.dispatch(request) diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/web3swift/Transaction/EthereumTransaction.swift index 336433f67..f043cc785 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/web3swift/Transaction/EthereumTransaction.swift @@ -193,7 +193,7 @@ public struct EthereumTransaction: CustomStringConvertible { if method == .estimateGas || transactionOptions?.gasLimit == nil { txParams.gas = nil } - var params: [JSONRPCParameter] = [.transaction(txParams)] + var params: [RPCParameter] = [.transaction(txParams)] if let onBlock = onBlock, method.requiredNumOfParameters == 2 { params.append(.string(onBlock)) } @@ -216,7 +216,7 @@ public struct EthereumTransaction: CustomStringConvertible { let hex = encodedData.toHexString().addHexPrefix().lowercased() var request = JSONRPCrequest() request.method = JSONRPCmethod.sendRawTransaction - let params: [JSONRPCParameter] = [.string(hex)] + let params: [RPCParameter] = [.string(hex)] request.params = params if !request.isValid { return nil } return request diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index fc92f5369..49efaa6ef 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -124,7 +124,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { return socketProvider } - public func writeMessage(method: InfuraWebsocketMethod, params: [Encodable]) throws { + public func writeMessage(method: InfuraWebsocketMethod, params: [JSONRPCParameter]) throws { let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params) let encoder = JSONEncoder() let requestData = try encoder.encode(request) @@ -132,7 +132,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { writeMessage(requestData) } - public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { + public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [JSONRPCParameter]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -149,7 +149,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { try setFilterAndGetChanges(method: method, params: [filterParams]) } - public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { + public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [JSONRPCParameter]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -200,7 +200,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { } } - public func subscribe(params: [Encodable]) throws { + public func subscribe(params: [JSONRPCParameter]) throws { let method = InfuraWebsocketMethod.subscribe try writeMessage(method: method, params: params) } diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index adaa68e6c..f2b207f54 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -26,7 +26,7 @@ public struct Counter { public struct JSONRPCrequest: Encodable { public var jsonrpc: String = "2.0" public var method: JSONRPCmethod? - public var params: [JSONRPCParameter] = [] + public var params: [RPCParameter] = [] public var id: UInt64 = Counter.increment() enum CodingKeys: String, CodingKey { @@ -286,6 +286,46 @@ public struct EventFilterParameters: Codable { public var address: [String?]? } +/// Protocol to restrict supported types which can be passed into `JSONRPCRequest` to a node. +/// +/// You **must not** conform any type to that protocol. +/// +/// Due to internal logic and swift itself restrictions, there's lack of encoding generic types +/// so current implementation of `JSONRPCParameter`s belongs on hardcoded supported types. +/// +/// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). +/// +/// Please see `RPCParameter` documentation for more details. +public protocol JSONRPCParameter: Encodable { } + +protocol JSONParameterElement: Encodable { } + +extension Int: JSONRPCParameter { } + +extension UInt: JSONRPCParameter { } + +extension UInt64: JSONRPCParameter { } + +extension Double: JSONRPCParameter { } + +extension String: JSONRPCParameter { } + +extension Bool: JSONRPCParameter { } + +extension Array: JSONRPCParameter where Element: JSONParameterElement { } + +extension TransactionParameters: JSONRPCParameter { } + +extension EventFilterParameters: JSONRPCParameter { } + +extension Double: JSONParameterElement { } + +extension Int: JSONParameterElement { } + +extension UInt64: JSONParameterElement { } + +extension String: JSONParameterElement { } + /** Enum to compose request to the node params. @@ -299,7 +339,7 @@ public struct EventFilterParameters: Codable { So in our case we're using such to implement custom `encode` method to any used in node request params types. - Latter is required to encode array of `JSONRPCParameter` to not to `[JSONRPCParameter.int(1)]`, but to `[1]`. + Latter is required to encode array of `RPCParameter` to not to `[RPCParameter.int(1)]`, but to `[1]`. Here's an example of using this enum in field. ```swift @@ -314,10 +354,13 @@ public struct EventFilterParameters: Codable { //> [12,\"this\",12.2,[12.2,12.4]]` ``` */ -public enum JSONRPCParameter { +public enum RPCParameter { case int(Int) case intArray([Int]) + case uint(UInt64) + case uintArray([UInt64]) + case double(Double) case doubleArray([Double]) @@ -330,16 +373,16 @@ public enum JSONRPCParameter { } -extension JSONRPCParameter: RawRepresentable { +extension RPCParameter: RawRepresentable { /** This init required by `RawRepresentable` protocol, which is requred to encode mixed type values array in JSON. This protocol used to implement custom `encode` method for that enum, which is encodes array of self into array of self assotiated values. - You're totally free to use explicit and more convenience member init as `JSONRPCParameter.int(12)` in your code. + You're totally free to use explicit and more convenience member init as `RPCParameter.int(12)` in your code. */ - public init?(rawValue: Encodable) { + public init?(rawValue: JSONRPCParameter) { /// force casting in this switch is safe because /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type // swiftlint:disable force_cast @@ -347,6 +390,9 @@ extension JSONRPCParameter: RawRepresentable { case is Int.Type: self = .int(rawValue as! Int) case is [Int].Type: self = .intArray(rawValue as! [Int]) + case is UInt64.Type: self = .uint(rawValue as! UInt64) + case is [UInt64].Type: self = .uintArray(rawValue as! [UInt64]) + case is String.Type: self = .string(rawValue as! String) case is [String].Type: self = .stringArray(rawValue as! [String]) @@ -361,13 +407,16 @@ extension JSONRPCParameter: RawRepresentable { // swiftlint:enable force_cast } - /// Returning associated value of the enum case only. - public var rawValue: Encodable { + /// Returning associated value of the enum case. + public var rawValue: JSONRPCParameter { // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. switch self { case let .int(value): return value case let .intArray(value): return value + case let .uint(value): return value + case let .uintArray(value): return value + case let .string(value): return value case let .stringArray(value): return value @@ -381,14 +430,14 @@ extension JSONRPCParameter: RawRepresentable { } } -extension JSONRPCParameter: Encodable { +extension RPCParameter: Encodable { /** - This encoder encodes `JSONRPCParameter` assotiated value ignoring self value + This encoder encodes `RPCParameter` assotiated value ignoring self value This is required to encode mixed types array, like ```swift - let someArray: [JSONRPCParameter] = [ + let someArray: [RPCParameter] = [ .init(rawValue: 12)!, .init(rawValue: "this")!, .init(rawValue: 12.2)!, @@ -408,6 +457,9 @@ extension JSONRPCParameter: Encodable { case is Int.Type: try enumContainer.encode(rawValue as! Int) case is [Int].Type: try enumContainer.encode(rawValue as! [Int]) + case is UInt64.Type: try enumContainer.encode(rawValue as! UInt64) + case is [UInt64].Type: try enumContainer.encode(rawValue as! [UInt64]) + case is String.Type: try enumContainer.encode(rawValue as! String) case is [String].Type: try enumContainer.encode(rawValue as! [String]) @@ -417,7 +469,7 @@ extension JSONRPCParameter: Encodable { case is Bool.Type: try enumContainer.encode(rawValue as! Bool) case is TransactionParameters.Type: try enumContainer.encode(rawValue as! TransactionParameters) case is EventFilterParameters.Type: try enumContainer.encode(rawValue as! EventFilterParameters) - default: break + default: break /// can't be executed, coz possible `self.rawValue` types are strictly defined in it's inplementation.` } // swiftlint:enable force_cast } diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index d662d3726..e5f27d0a7 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -75,17 +75,17 @@ public enum JSONRPCmethod: String, Encodable { } public struct JSONRPCRequestFabric { - public static func prepareRequest(_ method: JSONRPCmethod, parameters: [Encodable]) -> JSONRPCrequest { + public static func prepareRequest(_ method: JSONRPCmethod, parameters: [JSONRPCParameter]) -> JSONRPCrequest { var request = JSONRPCrequest() request.method = method - request.params = parameters.compactMap { JSONRPCParameter.init(rawValue: $0) } + request.params = parameters.compactMap { RPCParameter.init(rawValue: $0) } return request } - public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [Encodable]) -> InfuraWebsocketRequest { + public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [JSONRPCParameter]) -> InfuraWebsocketRequest { var request = InfuraWebsocketRequest() request.method = method - request.params = parameters.compactMap { JSONRPCParameter.init(rawValue: $0) } + request.params = parameters.compactMap { RPCParameter.init(rawValue: $0) } return request } } diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index bb22d485e..e6447445e 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -56,7 +56,7 @@ public enum InfuraWebsocketMethod: String, Encodable { public struct InfuraWebsocketRequest: Encodable { public var jsonrpc: String = "2.0" public var method: InfuraWebsocketMethod? - public var params: [JSONRPCParameter] = [] + public var params: [RPCParameter] = [] public var id: UInt64 = Counter.increment() enum CodingKeys: String, CodingKey { From 72e7ad9acc94eda9e4ce8f9b3b12cf824cd9177a Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 18 May 2022 13:35:55 +0700 Subject: [PATCH 08/45] Move JSONRPCParameter to separate file. --- Sources/web3swift/Web3/Web3+JSONRPC.swift | 189 ----------------- .../Web3/Web3+JSONRPCParameter.swift | 194 ++++++++++++++++++ 2 files changed, 194 insertions(+), 189 deletions(-) create mode 100644 Sources/web3swift/Web3/Web3+JSONRPCParameter.swift diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index f2b207f54..0eddac9a0 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -285,192 +285,3 @@ public struct EventFilterParameters: Codable { public var topics: [[String?]?]? public var address: [String?]? } - -/// Protocol to restrict supported types which can be passed into `JSONRPCRequest` to a node. -/// -/// You **must not** conform any type to that protocol. -/// -/// Due to internal logic and swift itself restrictions, there's lack of encoding generic types -/// so current implementation of `JSONRPCParameter`s belongs on hardcoded supported types. -/// -/// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). -/// -/// Please see `RPCParameter` documentation for more details. -public protocol JSONRPCParameter: Encodable { } - -protocol JSONParameterElement: Encodable { } - -extension Int: JSONRPCParameter { } - -extension UInt: JSONRPCParameter { } - -extension UInt64: JSONRPCParameter { } - -extension Double: JSONRPCParameter { } - -extension String: JSONRPCParameter { } - -extension Bool: JSONRPCParameter { } - -extension Array: JSONRPCParameter where Element: JSONParameterElement { } - -extension TransactionParameters: JSONRPCParameter { } - -extension EventFilterParameters: JSONRPCParameter { } - -extension Double: JSONParameterElement { } - -extension Int: JSONParameterElement { } - -extension UInt64: JSONParameterElement { } - -extension String: JSONParameterElement { } - -/** - Enum to compose request to the node params. - - In most cases request params are passed to Ethereum JSON RPC request as array of mixed type values, such as `[12,"this",true]`, - thus this is not appropriate API design we have what we have. - - Meanwhile swift don't provide strict way to compose such array it gives some hacks to solve this task - and one of them is using `RawRepresentable` protocol. - - Conforming this protocol gives designated type ability to represent itself in `String` representation in any way. - - So in our case we're using such to implement custom `encode` method to any used in node request params types. - - Latter is required to encode array of `RPCParameter` to not to `[RPCParameter.int(1)]`, but to `[1]`. - - Here's an example of using this enum in field. - ```swift - let jsonRPCParams: [JSONRPCParameter] = [ - .init(rawValue: 12)!, - .init(rawValue: "this")!, - .init(rawValue: 12.2)!, - .init(rawValue: [12.2, 12.4])! - ] - let encoded = try JSONEncoder().encode(jsonRPCParams) - print(String(data: encoded, encoding: .utf8)!) - //> [12,\"this\",12.2,[12.2,12.4]]` - ``` - */ -public enum RPCParameter { - case int(Int) - case intArray([Int]) - - case uint(UInt64) - case uintArray([UInt64]) - - case double(Double) - case doubleArray([Double]) - - case string(String) - case stringArray([String]) - - case bool(Bool) - case transaction(TransactionParameters) - case eventFilter(EventFilterParameters) -} - - -extension RPCParameter: RawRepresentable { - /** - This init required by `RawRepresentable` protocol, which is requred to encode mixed type values array in JSON. - - This protocol used to implement custom `encode` method for that enum, - which is encodes array of self into array of self assotiated values. - - You're totally free to use explicit and more convenience member init as `RPCParameter.int(12)` in your code. - */ - public init?(rawValue: JSONRPCParameter) { - /// force casting in this switch is safe because - /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type - // swiftlint:disable force_cast - switch type(of: rawValue) { - case is Int.Type: self = .int(rawValue as! Int) - case is [Int].Type: self = .intArray(rawValue as! [Int]) - - case is UInt64.Type: self = .uint(rawValue as! UInt64) - case is [UInt64].Type: self = .uintArray(rawValue as! [UInt64]) - - case is String.Type: self = .string(rawValue as! String) - case is [String].Type: self = .stringArray(rawValue as! [String]) - - case is Double.Type: self = .double(rawValue as! Double) - case is [Double].Type: self = .doubleArray(rawValue as! [Double]) - - case is Bool.Type: self = .bool(rawValue as! Bool) - case is TransactionParameters.Type: self = .transaction(rawValue as! TransactionParameters) - case is EventFilterParameters.Type: self = .eventFilter(rawValue as! EventFilterParameters) - default: return nil - } - // swiftlint:enable force_cast - } - - /// Returning associated value of the enum case. - public var rawValue: JSONRPCParameter { - // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. - switch self { - case let .int(value): return value - case let .intArray(value): return value - - case let .uint(value): return value - case let .uintArray(value): return value - - case let .string(value): return value - case let .stringArray(value): return value - - case let .double(value): return value - case let .doubleArray(value): return value - - case let .bool(value): return value - case let .transaction(value): return value - case let .eventFilter(value): return value - } - } -} - -extension RPCParameter: Encodable { - /** - This encoder encodes `RPCParameter` assotiated value ignoring self value - - This is required to encode mixed types array, like - - ```swift - let someArray: [RPCParameter] = [ - .init(rawValue: 12)!, - .init(rawValue: "this")!, - .init(rawValue: 12.2)!, - .init(rawValue: [12.2, 12.4])! - ] - let encoded = try JSONEncoder().encode(someArray) - print(String(data: encoded, encoding: .utf8)!) - //> [12,\"this\",12.2,[12.2,12.4]]` - ``` - */ - public func encode(to encoder: Encoder) throws { - var enumContainer = encoder.singleValueContainer() - /// force casting in this switch is safe because - /// each `rawValue` forced to casts only in exact case which is runs based on `rawValue` type - // swiftlint:disable force_cast - switch type(of: self.rawValue) { - case is Int.Type: try enumContainer.encode(rawValue as! Int) - case is [Int].Type: try enumContainer.encode(rawValue as! [Int]) - - case is UInt64.Type: try enumContainer.encode(rawValue as! UInt64) - case is [UInt64].Type: try enumContainer.encode(rawValue as! [UInt64]) - - case is String.Type: try enumContainer.encode(rawValue as! String) - case is [String].Type: try enumContainer.encode(rawValue as! [String]) - - case is Double.Type: try enumContainer.encode(rawValue as! Double) - case is [Double].Type: try enumContainer.encode(rawValue as! [Double]) - - case is Bool.Type: try enumContainer.encode(rawValue as! Bool) - case is TransactionParameters.Type: try enumContainer.encode(rawValue as! TransactionParameters) - case is EventFilterParameters.Type: try enumContainer.encode(rawValue as! EventFilterParameters) - default: break /// can't be executed, coz possible `self.rawValue` types are strictly defined in it's inplementation.` - } - // swiftlint:enable force_cast - } -} diff --git a/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift b/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift new file mode 100644 index 000000000..614f13417 --- /dev/null +++ b/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift @@ -0,0 +1,194 @@ +// Package: web3swift +// Created by Alex Vlasov. +// Copyright © 2022 Yaroslav Yashin. All rights reserved. + +/// Protocol to restrict supported types which can be passed into `JSONRPCRequest` to a node. +/// +/// You **must not** conform any type to that protocol. +/// +/// Due to internal logic and swift itself restrictions, there's lack of encoding generic types +/// so current implementation of `JSONRPCParameter`s belongs on hardcoded supported types. +/// +/// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). +/// +/// Please see `RPCParameter` documentation for more details. +public protocol JSONRPCParameter: Encodable { } + +protocol JSONParameterElement: Encodable { } + +extension Int: JSONRPCParameter { } + +extension UInt: JSONRPCParameter { } + +// FIXME: Drop all non default types support +extension UInt64: JSONRPCParameter { } + +extension Double: JSONRPCParameter { } + +extension String: JSONRPCParameter { } + +extension Bool: JSONRPCParameter { } + +extension Array: JSONRPCParameter where Element: JSONParameterElement { } + +extension TransactionParameters: JSONRPCParameter { } + +extension EventFilterParameters: JSONRPCParameter { } + +extension Double: JSONParameterElement { } + +extension Int: JSONParameterElement { } + +// FIXME: Drop all non default types support +extension UInt64: JSONParameterElement { } + +extension String: JSONParameterElement { } + +/** + Enum to compose request to the node params. + + In most cases request params are passed to Ethereum JSON RPC request as array of mixed type values, such as `[12,"this",true]`, + thus this is not appropriate API design we have what we have. + + Meanwhile swift don't provide strict way to compose such array it gives some hacks to solve this task + and one of them is using `RawRepresentable` protocol. + + Conforming this protocol gives designated type ability to represent itself in `String` representation in any way. + + So in our case we're using such to implement custom `encode` method to any used in node request params types. + + Latter is required to encode array of `RPCParameter` to not to `[RPCParameter.int(1)]`, but to `[1]`. + + Here's an example of using this enum in field. + ```swift + let jsonRPCParams: [JSONRPCParameter] = [ + .init(rawValue: 12)!, + .init(rawValue: "this")!, + .init(rawValue: 12.2)!, + .init(rawValue: [12.2, 12.4])! + ] + let encoded = try JSONEncoder().encode(jsonRPCParams) + print(String(data: encoded, encoding: .utf8)!) + //> [12,\"this\",12.2,[12.2,12.4]]` + ``` + */ +public enum RPCParameter { + case int(Int) + case intArray([Int]) + + case uint(UInt64) + case uintArray([UInt64]) + + case double(Double) + case doubleArray([Double]) + + case string(String) + case stringArray([String]) + + case bool(Bool) + case transaction(TransactionParameters) + case eventFilter(EventFilterParameters) +} + + +extension RPCParameter: RawRepresentable { + /** + This init required by `RawRepresentable` protocol, which is requred to encode mixed type values array in JSON. + + This protocol used to implement custom `encode` method for that enum, + which is encodes array of self into array of self assotiated values. + + You're totally free to use explicit and more convenience member init as `RPCParameter.int(12)` in your code. + */ + public init?(rawValue: JSONRPCParameter) { + /// force casting in this switch is safe because + /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type + // swiftlint:disable force_cast + switch type(of: rawValue) { + case is Int.Type: self = .int(rawValue as! Int) + case is [Int].Type: self = .intArray(rawValue as! [Int]) + + case is UInt64.Type: self = .uint(rawValue as! UInt64) + case is [UInt64].Type: self = .uintArray(rawValue as! [UInt64]) + + case is String.Type: self = .string(rawValue as! String) + case is [String].Type: self = .stringArray(rawValue as! [String]) + + case is Double.Type: self = .double(rawValue as! Double) + case is [Double].Type: self = .doubleArray(rawValue as! [Double]) + + case is Bool.Type: self = .bool(rawValue as! Bool) + case is TransactionParameters.Type: self = .transaction(rawValue as! TransactionParameters) + case is EventFilterParameters.Type: self = .eventFilter(rawValue as! EventFilterParameters) + default: return nil + } + // swiftlint:enable force_cast + } + + /// Returning associated value of the enum case. + public var rawValue: JSONRPCParameter { + // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. + switch self { + case let .int(value): return value + case let .intArray(value): return value + + case let .uint(value): return value + case let .uintArray(value): return value + + case let .string(value): return value + case let .stringArray(value): return value + + case let .double(value): return value + case let .doubleArray(value): return value + + case let .bool(value): return value + case let .transaction(value): return value + case let .eventFilter(value): return value + } + } +} + +extension RPCParameter: Encodable { + /** + This encoder encodes `RPCParameter` assotiated value ignoring self value + + This is required to encode mixed types array, like + + ```swift + let someArray: [RPCParameter] = [ + .init(rawValue: 12)!, + .init(rawValue: "this")!, + .init(rawValue: 12.2)!, + .init(rawValue: [12.2, 12.4])! + ] + let encoded = try JSONEncoder().encode(someArray) + print(String(data: encoded, encoding: .utf8)!) + //> [12,\"this\",12.2,[12.2,12.4]]` + ``` + */ + public func encode(to encoder: Encoder) throws { + var enumContainer = encoder.singleValueContainer() + /// force casting in this switch is safe because + /// each `rawValue` forced to casts only in exact case which is runs based on `rawValue` type + // swiftlint:disable force_cast + switch type(of: self.rawValue) { + case is Int.Type: try enumContainer.encode(rawValue as! Int) + case is [Int].Type: try enumContainer.encode(rawValue as! [Int]) + + case is UInt64.Type: try enumContainer.encode(rawValue as! UInt64) + case is [UInt64].Type: try enumContainer.encode(rawValue as! [UInt64]) + + case is String.Type: try enumContainer.encode(rawValue as! String) + case is [String].Type: try enumContainer.encode(rawValue as! [String]) + + case is Double.Type: try enumContainer.encode(rawValue as! Double) + case is [Double].Type: try enumContainer.encode(rawValue as! [Double]) + + case is Bool.Type: try enumContainer.encode(rawValue as! Bool) + case is TransactionParameters.Type: try enumContainer.encode(rawValue as! TransactionParameters) + case is EventFilterParameters.Type: try enumContainer.encode(rawValue as! EventFilterParameters) + default: break /// can't be executed, coz possible `self.rawValue` types are strictly defined in it's inplementation.` + } + // swiftlint:enable force_cast + } +} From 9f79702f652b5f75c1b164787b907a87f0fb42fd Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 19 May 2022 16:14:19 +0700 Subject: [PATCH 09/45] Update UInt64 to UInt since this accuracy isn't required. --- Sources/web3swift/Web3/Web3+JSONRPC.swift | 10 ++++++---- Sources/web3swift/Web3/Web3+WebsocketProvider.swift | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index 0eddac9a0..8850f9368 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -3,16 +3,18 @@ // Copyright © 2018 Alex Vlasov. All rights reserved. // // Additions to support new transaction types by Mark Loit March 2022 +// +// Made most structs generics by Yaroslav Yashin 2022 import Foundation import BigInt /// Global counter object to enumerate JSON RPC requests. public struct Counter { - public static var counter = UInt64(1) + public static var counter = UInt(1) public static var lockQueue = DispatchQueue(label: "counterQueue") - public static func increment() -> UInt64 { - var c: UInt64 = 0 + public static func increment() -> UInt { + var c: UInt = 0 lockQueue.sync { c = Counter.counter Counter.counter = Counter.counter + 1 @@ -27,7 +29,7 @@ public struct JSONRPCrequest: Encodable { public var jsonrpc: String = "2.0" public var method: JSONRPCmethod? public var params: [RPCParameter] = [] - public var id: UInt64 = Counter.increment() + public var id: UInt = Counter.increment() enum CodingKeys: String, CodingKey { case jsonrpc diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index e6447445e..c9dacc027 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -57,7 +57,7 @@ public struct InfuraWebsocketRequest: Encodable { public var jsonrpc: String = "2.0" public var method: InfuraWebsocketMethod? public var params: [RPCParameter] = [] - public var id: UInt64 = Counter.increment() + public var id = Counter.increment() enum CodingKeys: String, CodingKey { case jsonrpc From d7953dcae5644339ec738e4a0f5fed09c74e68cb Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 14:23:32 +0700 Subject: [PATCH 10/45] Change UInt64 to UInt. ABI API left unchanged. --- .../web3swift/Contract/ContractProtocol.swift | 2 +- .../Convenience/Decodable+Extensions.swift | 2 +- .../Promise+Web3+Eth+GetBlockByNumber.swift | 2 +- .../Promise+Web3+Personal+UnlockAccount.swift | 4 +-- Sources/web3swift/Web3/Web3+Eth.swift | 2 +- Sources/web3swift/Web3/Web3+EventParser.swift | 4 +-- Sources/web3swift/Web3/Web3+JSONRPC.swift | 2 +- .../Web3/Web3+JSONRPCParameter.swift | 32 +++++++++++-------- Sources/web3swift/Web3/Web3+Personal.swift | 2 +- Sources/web3swift/Web3/Web3+Protocols.swift | 4 +-- .../remoteTests/InfuraTests.swift | 8 ++--- .../remoteTests/RemoteParsingTests.swift | 8 ++--- 12 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Sources/web3swift/Contract/ContractProtocol.swift b/Sources/web3swift/Contract/ContractProtocol.swift index add29ba2e..eca4251bf 100755 --- a/Sources/web3swift/Contract/ContractProtocol.swift +++ b/Sources/web3swift/Contract/ContractProtocol.swift @@ -44,7 +44,7 @@ public struct EventFilter { public enum Block { case latest case pending - case blockNumber(UInt64) + case blockNumber(UInt) var encoded: String { switch self { diff --git a/Sources/web3swift/Convenience/Decodable+Extensions.swift b/Sources/web3swift/Convenience/Decodable+Extensions.swift index b42a0727d..ee0c05cff 100644 --- a/Sources/web3swift/Convenience/Decodable+Extensions.swift +++ b/Sources/web3swift/Convenience/Decodable+Extensions.swift @@ -146,7 +146,7 @@ extension Date: DecodableFromHex { public init?(fromHex hexString: String) { self.init() let stripedHexString = hexString.stripHexPrefix() - guard let timestampInt = UInt64(stripedHexString, radix: 16) else { return nil } + guard let timestampInt = UInt(stripedHexString, radix: 16) else { return nil } self = Date(timeIntervalSince1970: TimeInterval(timestampInt)) } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift index 273301ce6..eeaf9bb93 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift @@ -9,7 +9,7 @@ import BigInt extension web3.Eth { - public func blockBy(number: UInt64, fullTransactions: Bool = false) async throws -> Block { + public func blockBy(number: UInt, fullTransactions: Bool = false) async throws -> Block { let block = String(number, radix: 16).addHexPrefix() return try await blockBy(number: block, fullTransactions: fullTransactions) } diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift index 7a4e5f546..cae10658b 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift @@ -9,12 +9,12 @@ import BigInt extension web3.Personal { - public func unlock(account: EthereumAddress, password: String = "web3swift", seconds: UInt64 = 300) async throws -> Bool { + public func unlock(account: EthereumAddress, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { let addr = account.address return try await unlock(account: addr, password: password, seconds: seconds) } - public func unlock(account: String, password: String = "web3swift", seconds: UInt64 = 300) async throws -> Bool { + public func unlock(account: String, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { guard self.web3.provider.attachedKeystoreManager == nil else { throw Web3Error.inputError(desc: "Can not unlock a local keystore") diff --git a/Sources/web3swift/Web3/Web3+Eth.swift b/Sources/web3swift/Web3/Web3+Eth.swift index c1658be07..d485de6ab 100755 --- a/Sources/web3swift/Web3/Web3+Eth.swift +++ b/Sources/web3swift/Web3/Web3+Eth.swift @@ -208,7 +208,7 @@ extension web3.Eth { /// This function is synchronous! /// /// Returns the Result object that indicates either success of failure. - public func getBlockByNumber(_ number: UInt64, fullTransactions: Bool = false) async throws -> Block { + public func getBlockByNumber(_ number: UInt, fullTransactions: Bool = false) async throws -> Block { let result = try await self.blockBy(number: number, fullTransactions: fullTransactions) return result } diff --git a/Sources/web3swift/Web3/Web3+EventParser.swift b/Sources/web3swift/Web3/Web3+EventParser.swift index 6b75cb048..8587b801f 100755 --- a/Sources/web3swift/Web3/Web3+EventParser.swift +++ b/Sources/web3swift/Web3/Web3+EventParser.swift @@ -36,7 +36,7 @@ extension web3.web3contract { - important: This call is synchronous */ - public func parseBlockByNumber(_ blockNumber: UInt64) async throws -> [EventParserResultProtocol] { + public func parseBlockByNumber(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] { let result = try await self.parseBlockByNumberPromise(blockNumber) return result } @@ -112,7 +112,7 @@ extension web3.web3contract.EventParser { } - public func parseBlockByNumberPromise(_ blockNumber: UInt64) async throws -> [EventParserResultProtocol] { + public func parseBlockByNumberPromise(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] { guard filter == nil || filter?.fromBlock == nil && filter?.toBlock == nil else { throw Web3Error.inputError(desc: "Can not mix parsing specific block and using block range filter") diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index 8850f9368..0400ec965 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -11,7 +11,7 @@ import BigInt /// Global counter object to enumerate JSON RPC requests. public struct Counter { - public static var counter = UInt(1) + public static var counter: UInt = 1 public static var lockQueue = DispatchQueue(label: "counterQueue") public static func increment() -> UInt { var c: UInt = 0 diff --git a/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift b/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift index 614f13417..363923275 100644 --- a/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift @@ -20,9 +20,6 @@ extension Int: JSONRPCParameter { } extension UInt: JSONRPCParameter { } -// FIXME: Drop all non default types support -extension UInt64: JSONRPCParameter { } - extension Double: JSONRPCParameter { } extension String: JSONRPCParameter { } @@ -35,15 +32,16 @@ extension TransactionParameters: JSONRPCParameter { } extension EventFilterParameters: JSONRPCParameter { } -extension Double: JSONParameterElement { } - extension Int: JSONParameterElement { } -// FIXME: Drop all non default types support -extension UInt64: JSONParameterElement { } +extension UInt: JSONParameterElement { } + +extension Double: JSONParameterElement { } extension String: JSONParameterElement { } +extension Bool: JSONParameterElement { } + /** Enum to compose request to the node params. @@ -76,8 +74,8 @@ public enum RPCParameter { case int(Int) case intArray([Int]) - case uint(UInt64) - case uintArray([UInt64]) + case uint(UInt) + case uintArray([UInt]) case double(Double) case doubleArray([Double]) @@ -86,6 +84,8 @@ public enum RPCParameter { case stringArray([String]) case bool(Bool) + case boolArray([Bool]) + case transaction(TransactionParameters) case eventFilter(EventFilterParameters) } @@ -108,8 +108,8 @@ extension RPCParameter: RawRepresentable { case is Int.Type: self = .int(rawValue as! Int) case is [Int].Type: self = .intArray(rawValue as! [Int]) - case is UInt64.Type: self = .uint(rawValue as! UInt64) - case is [UInt64].Type: self = .uintArray(rawValue as! [UInt64]) + case is UInt.Type: self = .uint(rawValue as! UInt) + case is [UInt].Type: self = .uintArray(rawValue as! [UInt]) case is String.Type: self = .string(rawValue as! String) case is [String].Type: self = .stringArray(rawValue as! [String]) @@ -118,6 +118,8 @@ extension RPCParameter: RawRepresentable { case is [Double].Type: self = .doubleArray(rawValue as! [Double]) case is Bool.Type: self = .bool(rawValue as! Bool) + case is [Bool].Type: self = .boolArray(rawValue as! [Bool]) + case is TransactionParameters.Type: self = .transaction(rawValue as! TransactionParameters) case is EventFilterParameters.Type: self = .eventFilter(rawValue as! EventFilterParameters) default: return nil @@ -142,6 +144,8 @@ extension RPCParameter: RawRepresentable { case let .doubleArray(value): return value case let .bool(value): return value + case let .boolArray(value): return value + case let .transaction(value): return value case let .eventFilter(value): return value } @@ -175,8 +179,8 @@ extension RPCParameter: Encodable { case is Int.Type: try enumContainer.encode(rawValue as! Int) case is [Int].Type: try enumContainer.encode(rawValue as! [Int]) - case is UInt64.Type: try enumContainer.encode(rawValue as! UInt64) - case is [UInt64].Type: try enumContainer.encode(rawValue as! [UInt64]) + case is UInt.Type: try enumContainer.encode(rawValue as! UInt) + case is [UInt].Type: try enumContainer.encode(rawValue as! [UInt]) case is String.Type: try enumContainer.encode(rawValue as! String) case is [String].Type: try enumContainer.encode(rawValue as! [String]) @@ -185,6 +189,8 @@ extension RPCParameter: Encodable { case is [Double].Type: try enumContainer.encode(rawValue as! [Double]) case is Bool.Type: try enumContainer.encode(rawValue as! Bool) + case is [Bool].Type: try enumContainer.encode(rawValue as! [Bool]) + case is TransactionParameters.Type: try enumContainer.encode(rawValue as! TransactionParameters) case is EventFilterParameters.Type: try enumContainer.encode(rawValue as! EventFilterParameters) default: break /// can't be executed, coz possible `self.rawValue` types are strictly defined in it's inplementation.` diff --git a/Sources/web3swift/Web3/Web3+Personal.swift b/Sources/web3swift/Web3/Web3+Personal.swift index cbf2e9b90..2004906d0 100755 --- a/Sources/web3swift/Web3/Web3+Personal.swift +++ b/Sources/web3swift/Web3/Web3+Personal.swift @@ -42,7 +42,7 @@ extension web3.Personal { - important: This call is synchronous. Does nothing if private keys are stored locally. */ - public func unlockAccount(account: EthereumAddress, password: String = "web3swift", seconds: UInt64 = 300) async throws -> Bool { + public func unlockAccount(account: EthereumAddress, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { let result = try await self.unlock(account: account) return result } diff --git a/Sources/web3swift/Web3/Web3+Protocols.swift b/Sources/web3swift/Web3/Web3+Protocols.swift index b1152c827..ae264fc34 100755 --- a/Sources/web3swift/Web3/Web3+Protocols.swift +++ b/Sources/web3swift/Web3/Web3+Protocols.swift @@ -21,10 +21,10 @@ public protocol EventParserProtocol { func parseTransaction(_ transaction: EthereumTransaction) async throws -> [EventParserResultProtocol] func parseTransactionByHash(_ hash: Data) async throws -> [EventParserResultProtocol] func parseBlock(_ block: Block) async throws -> [EventParserResultProtocol] - func parseBlockByNumber(_ blockNumber: UInt64) async throws -> [EventParserResultProtocol] + func parseBlockByNumber(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] func parseTransactionPromise(_ transaction: EthereumTransaction) async throws -> [EventParserResultProtocol] func parseTransactionByHashPromise(_ hash: Data) async throws -> [EventParserResultProtocol] - func parseBlockByNumberPromise(_ blockNumber: UInt64) async throws -> [EventParserResultProtocol] + func parseBlockByNumberPromise(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] func parseBlockPromise(_ block: Block) async throws -> [EventParserResultProtocol] } diff --git a/Tests/web3swiftTests/remoteTests/InfuraTests.swift b/Tests/web3swiftTests/remoteTests/InfuraTests.swift index f4a7d93c9..2d4852ffe 100755 --- a/Tests/web3swiftTests/remoteTests/InfuraTests.swift +++ b/Tests/web3swiftTests/remoteTests/InfuraTests.swift @@ -38,7 +38,7 @@ class InfuraTests: XCTestCase { func testGetBlockByNumber2() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByNumber(UInt64(5184323), fullTransactions: true) + let result = try await web3.eth.getBlockByNumber(UInt(5184323), fullTransactions: true) print(result) let transactions = result.transactions for transaction in transactions { @@ -54,7 +54,7 @@ class InfuraTests: XCTestCase { func testGetBlockByNumber3() async throws { do { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let _ = try await web3.eth.getBlockByNumber(UInt64(1000000000), fullTransactions: true) + let _ = try await web3.eth.getBlockByNumber(UInt(1000000000), fullTransactions: true) XCTFail() } catch { @@ -72,8 +72,8 @@ class InfuraTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) let contract = web3.contract(jsonString, at: nil, abiVersion: 2) var filter = EventFilter() - filter.fromBlock = .blockNumber(UInt64(5200120)) - filter.toBlock = .blockNumber(UInt64(5200120)) + filter.fromBlock = .blockNumber(UInt(5200120)) + filter.toBlock = .blockNumber(UInt(5200120)) filter.addresses = [EthereumAddress("0x53066cddbc0099eb6c96785d9b3df2aaeede5da3")!] filter.parameterFilters = [([EthereumAddress("0xefdcf2c36f3756ce7247628afdb632fa4ee12ec5")!] as [EventFilterable]), (nil as [EventFilterable]?)] let eventParserResult = try await contract!.getIndexedEventsPromise(eventName: "Transfer", filter: filter, joinWithReceipts: true) diff --git a/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift b/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift index 955cd1edc..a6cdd5ca4 100755 --- a/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift +++ b/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift @@ -94,8 +94,8 @@ class RemoteParsingTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) let contract = web3.contract(jsonString, at: nil, abiVersion: 2) var filter = EventFilter() - filter.fromBlock = .blockNumber(UInt64(5200120)) - filter.toBlock = .blockNumber(UInt64(5200120)) + filter.fromBlock = .blockNumber(UInt(5200120)) + filter.toBlock = .blockNumber(UInt(5200120)) filter.addresses = [EthereumAddress("0x53066cddbc0099eb6c96785d9b3df2aaeede5da3")!] filter.parameterFilters = [([EthereumAddress("0xefdcf2c36f3756ce7247628afdb632fa4ee12ec5")!] as [EventFilterable]), ([EthereumAddress("0xd5395c132c791a7f46fa8fc27f0ab6bacd824484")!] as [EventFilterable])] guard let result = try await contract?.getIndexedEvents(eventName: "Transfer", filter: filter) else {return XCTFail()} @@ -107,8 +107,8 @@ class RemoteParsingTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) let contract = web3.contract(jsonString, at: nil, abiVersion: 2) var filter = EventFilter() - filter.fromBlock = .blockNumber(UInt64(5200120)) - filter.toBlock = .blockNumber(UInt64(5200120)) + filter.fromBlock = .blockNumber(UInt(5200120)) + filter.toBlock = .blockNumber(UInt(5200120)) filter.addresses = [EthereumAddress("0x53066cddbc0099eb6c96785d9b3df2aaeede5da3")!] filter.parameterFilters = [([EthereumAddress("0xefdcf2c36f3756ce7247628afdb632fa4ee12ec5")!] as [EventFilterable]), (nil as [EventFilterable]?)] guard let result = try await contract?.getIndexedEvents(eventName: "Transfer", filter: filter) else {return XCTFail()} From e439b043e820cc3299bf0f197795f06243027d50 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 14:24:01 +0700 Subject: [PATCH 11/45] Remove commented out piece of code --- .../Convenience/RIPEMD160+StackOveflow.swift | 86 ------------------- .../web3swift/EthereumABI/ABIEncoding.swift | 1 - .../Promise+Web3+Eth+FeeHistory.swift | 1 - 3 files changed, 88 deletions(-) diff --git a/Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift b/Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift index d74481630..8fceeafe9 100755 --- a/Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift +++ b/Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift @@ -391,92 +391,6 @@ public struct RIPEMD160 { return data } - - // public mutating func update(data: Data) throws { - // try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in - // - // if let bodyAddress = body.baseAddress, body.count > 0 { - // var ptr = bodyAddress.assumingMemoryBound(to: UInt8.self) - // var length = data.count - // var X = [UInt32](repeating: 0, count: 16) - // - // // Process remaining bytes from last call: - // if buffer.count > 0 && buffer.count + length >= 64 { - // let amount = 64 - buffer.count - // buffer.append(ptr, count: amount) - // try buffer.withUnsafeBytes { (body: UnsafeRawBufferPointer) in - // if let bodyAddress = body.baseAddress, body.count > 0 { - // let pointer = bodyAddress.assumingMemoryBound(to: Void.self) - // _ = memcpy(&X, pointer, 64) - // } else { - // throw Web3Error.dataError - // } - // } - // compress(X) - // ptr += amount - // length -= amount - // } - // // Process 64 byte chunks: - // while length >= 64 { - // memcpy(&X, ptr, 64) - // compress(X) - // ptr += 64 - // length -= 64 - // } - // // Save remaining unprocessed bytes: - // buffer = Data(bytes: ptr, count: length) - // } else { - // throw Web3Error.dataError - // } - // - // } - // count += Int64(data.count) - // } - // - // public mutating func finalize() throws -> Data { - // var X = [UInt32](repeating: 0, count: 16) - // /* append the bit m_n == 1 */ - // buffer.append(0x80) - // try buffer.withUnsafeBytes { (body: UnsafeRawBufferPointer) in - // if let bodyAddress = body.baseAddress, body.count > 0 { - // let pointer = bodyAddress.assumingMemoryBound(to: Void.self) - // _ = memcpy(&X, pointer, buffer.count) - // } else { - // throw Web3Error.dataError - // } - // } - // - // if (count & 63) > 55 { - // /* length goes to next block */ - // compress(X) - // X = [UInt32](repeating: 0, count: 16) - // } - // - // /* append length in bits */ - // let lswlen = UInt32(truncatingIfNeeded: count) - // let mswlen = UInt32(UInt64(count) >> 32) - // X[14] = lswlen << 3 - // X[15] = (lswlen >> 29) | (mswlen << 3) - // compress(X) - // - // var data = Data(count: 20) - // try data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in - // if let bodyAddress = body.baseAddress, body.count > 0 { - // let pointer = bodyAddress.assumingMemoryBound(to: UInt32.self) - // pointer[0] = MDbuf.0 - // pointer[1] = MDbuf.1 - // pointer[2] = MDbuf.2 - // pointer[3] = MDbuf.3 - // pointer[4] = MDbuf.4 - // } else { - // throw Web3Error.dataError - // } - // } - // - // buffer = Data() - // - // return data - // } } public extension RIPEMD160 { diff --git a/Sources/web3swift/EthereumABI/ABIEncoding.swift b/Sources/web3swift/EthereumABI/ABIEncoding.swift index c20982865..c0b32c2d3 100755 --- a/Sources/web3swift/EthereumABI/ABIEncoding.swift +++ b/Sources/web3swift/EthereumABI/ABIEncoding.swift @@ -256,7 +256,6 @@ extension ABIEncoder { toReturn.append(encoding) } let total = lengthEncoding + toReturn - // print("Dynamic array of static types encoding :\n" + String(total.toHexString())) return total } else { // create new context diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index dc3dd480d..91b00ff70 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -11,7 +11,6 @@ import BigInt extension web3.Eth { func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { - let parameters: [JSONRPCParameter] = [blockCount.description.addHexPrefix(), block, percentiles] let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: parameters) From 1a7734ebe4eecc47461749dccea67c689b30fae9 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 15:33:48 +0700 Subject: [PATCH 12/45] Make Counter.increment() static method mode clear --- Sources/web3swift/Web3/Web3+JSONRPC.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index 0400ec965..6d366d171 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -14,12 +14,12 @@ public struct Counter { public static var counter: UInt = 1 public static var lockQueue = DispatchQueue(label: "counterQueue") public static func increment() -> UInt { - var c: UInt = 0 - lockQueue.sync { - c = Counter.counter - Counter.counter = Counter.counter + 1 + defer { + lockQueue.sync { + Counter.counter += 1 + } } - return c + return counter } } From 8398c5df57c6c75880ff7494a9fca9d9d9566707 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 16:01:29 +0700 Subject: [PATCH 13/45] Fix feeHistory logic bug It didn't converts blocks amount into hex number system. --- .../Promise+Web3+Eth+FeeHistory.swift | 2 +- .../remoteTests/GasOracleTests.swift | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index 91b00ff70..efe67a81b 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -11,7 +11,7 @@ import BigInt extension web3.Eth { func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { - let parameters: [JSONRPCParameter] = [blockCount.description.addHexPrefix(), block, percentiles] + let parameters: [JSONRPCParameter] = [blockCount.hexString, block, percentiles] let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: parameters) let response = try await web3.dispatch(request) diff --git a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift index a236aa662..63fab36a6 100644 --- a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift +++ b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift @@ -19,10 +19,10 @@ class OracleTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) let etalonPercentiles: [BigUInt] = [ - 71456911562, // 10 percentile - 92735433497, // 40 percentile - 105739785122, // 60 percentile - 118929912191 // 90 percentile + 94217344703, // 10 percentile + 105983352568, // 40 percentile + 110561015933, // 60 percentile + 124178275323 // 90 percentile ] let baseFeePercentiles = await oracle.baseFeePercentiles() @@ -33,10 +33,10 @@ class OracleTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) let etalonPercentiles: [BigUInt] = [ - 1251559157, // 10 percentile - 1594062500, // 40 percentile - 2268157275, // 60 percentile - 11394017894 // 90 percentile + 1217066957, // 10 percentile + 1525000000, // 40 percentile + 2047260024, // 60 percentile + 9807181877 // 90 percentile ] let tipFeePercentiles = await oracle.tipFeePercentiles() @@ -48,16 +48,16 @@ class OracleTests: XCTestCase { lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) let etalonPercentiles: ([BigUInt], [BigUInt]) = ( baseFee: [ - 71456911562, // 10 percentile - 92735433497, // 40 percentile - 105739785122, // 60 percentile - 118929912191 // 90 percentile + 94217344703, // 10 percentile + 105983352568, // 40 percentile + 110561015933, // 60 percentile + 124178275323 // 90 percentile ], tip: [ - 1251559157, // 10 percentile - 1594062500, // 40 percentile - 2268157275, // 60 percentile - 11394017894 // 90 percentile + 1217066957, // 10 percentile + 1525000000, // 40 percentile + 2047260024, // 60 percentile + 9807181877 // 90 percentile ] ) From 8c0e1193911fb43463a3f7c2f5b65fd777524b11 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 20:09:06 +0700 Subject: [PATCH 14/45] Make async/await internal API consistent There were two API calls to same task for iOS 15 and pre iOS. Have made one to both cases. --- .../web3swift/Web3/Web3+HttpProvider.swift | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+HttpProvider.swift b/Sources/web3swift/Web3/Web3+HttpProvider.swift index 5e1afc633..d0a545822 100755 --- a/Sources/web3swift/Web3/Web3+HttpProvider.swift +++ b/Sources/web3swift/Web3/Web3+HttpProvider.swift @@ -58,18 +58,11 @@ public class Web3HttpProvider: Web3Provider { } fileprivate static func dataFrom(session: URLSession, request urlRequest: URLRequest) async throws -> Data{ - if #available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) { - let (data, _) = try await session.data(for: urlRequest) - return data - } else { - let (data, _) = try await session.data(forRequest: urlRequest) - // Fallback on earlier versions - return data - } + let (data, _) = try await session.data(for: urlRequest) + return data } static func post(_ request: U, providerURL: URL, session: URLSession) async throws -> T { - let requestData = try JSONEncoder().encode(request) var urlRequest = URLRequest(url: providerURL, cachePolicy: .reloadIgnoringCacheData) urlRequest.httpMethod = "POST" @@ -96,12 +89,14 @@ public class Web3HttpProvider: Web3Provider { return try await Web3HttpProvider.post(request, providerURL: self.url, session: self.session) } - public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { - return try await Web3HttpProvider.post(requests, providerURL: self.url, session: self.session) - } +// public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { +// return try await Web3HttpProvider.post(requests, providerURL: self.url, session: self.session) +// } } + @available(iOS, obsoleted: 15.0, message: "Use the built-in API instead") +@available(macOS, obsoleted: 12.0, message: "Use the built-in API instead") extension URLSession { func data(fromUrl url: URL) async throws -> (Data, URLResponse) { try await withCheckedThrowingContinuation { continuation in @@ -110,15 +105,13 @@ extension URLSession { let error = error ?? URLError(.badServerResponse) return continuation.resume(throwing: error) } - continuation.resume(returning: (data, response)) } - task.resume() } } - func data(forRequest request: URLRequest) async throws -> (Data, URLResponse) { + func data(for request: URLRequest) async throws -> (Data, URLResponse) { var dataTask: URLSessionDataTask? return try await withCheckedThrowingContinuation { continuation in @@ -127,10 +120,8 @@ extension URLSession { let error = error ?? URLError(.badServerResponse) return continuation.resume(throwing: error) } - continuation.resume(returning: (data, response)) } - dataTask?.resume() } } From dfe4f7240fe7223e93afb9f51c479b5c237faf66 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 22 May 2022 20:44:24 +0700 Subject: [PATCH 15/45] Delete duplicate BlockNumber enum in FeeHistory. --- Sources/web3swift/Web3/Web3+GasOracle.swift | 26 +++---------------- .../web3swift/Web3/Web3+InfuraProviders.swift | 4 +++ 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index 65aa16f7d..4bb4dbd24 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -89,7 +89,7 @@ extension Web3 { // TODO: Disabled until 3.0 version, coz `distance` available from iOS 13. // guard feeHistory == nil, forceDropCache, feeHistory!.timestamp.distance(to: Date()) > cacheTimeout else { return feeHistory! } - return try await eth.feeHistory(blockCount: blockCount, block: block.hexValue, percentiles: percentiles) + return try await eth.feeHistory(blockCount: blockCount, block: block.stringValue, percentiles: percentiles) } /// Suggesting tip values @@ -126,6 +126,9 @@ extension Web3 { switch block { case .latest: latestBlockNumber = try await eth.getBlockNumber() case let .exact(number): latestBlockNumber = number + // FIXME: Make real error here + // Error throws since pending and erliest are unable to be used in this method. + default: throw Web3Error.unknownError } /// checking if latest block number is greather than number of blocks to take in account @@ -242,24 +245,3 @@ extension Web3.Oracle.FeeHistory: Decodable { self.reward = try values.decodeHex([[BigUInt]].self, forKey: .reward) } } - - -public extension Web3 { - /// Enum for convenient type safe work with block number - enum BlockNumber { - /// Latest block of a chain - case latest - /// Exact block number - case exact(BigUInt) - - /// Block number as a string - /// - /// Could be `hexString` either `latest` - internal var hexValue: String { - switch self { - case .latest: return "latest" - case let .exact(number): return String(number, radix: 16).addHexPrefix() - } - } - } -} diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index 49efaa6ef..015e26a06 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -9,10 +9,14 @@ import Starscream public enum BlockNumber { case pending + /// Latest block of a chain case latest + /// Earliest block of a chain case earliest + /// Exact block number case exact(BigUInt) + /// Block number as a hex string public var stringValue: String { switch self { case .pending: From e4fcc1d90113bb7ca735b2ef088750c28b1e730f Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Mon, 23 May 2022 15:46:57 +0700 Subject: [PATCH 16/45] Add EthJSONRPC enum to encapsulate REST logic. --- Sources/web3swift/Web3/Web3+Methods.swift | 183 +++++++++++++++++++++- 1 file changed, 181 insertions(+), 2 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index e5f27d0a7..2edaa6f5c 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -6,8 +6,187 @@ import Foundation -public enum JSONRPCmethod: String, Encodable { +public typealias Hash = String // 32 bytes hash of block +public typealias Receipt = Hash +public typealias Address = Hash // 20 bytes + +/// Ethereum JSON RPC API Calls +public enum EthJSONRPC { + // MARK: - Official API + // 0 parameter in call + case gasPrice + case blockNumber + case getNetwork + case getAccounts + // ?? + case estimateGas + + case sendRawTransaction(Hash) + case sendTransaction(TransactionParameters) + case getTransactionByHash(Hash) + case getTransactionReceipt(Receipt) + case getLogs(EventFilterParameters) + case personalSign(Address, Data) + case call(EthereumTransaction) + case getTransactionCount(Address, BlockNumber) + case getBalance(Address, BlockNumber) + + /// Returns the value from a storage position at a given address. + /// + /// - Parameters: + /// - Address: Address + /// - Storage: slot + /// - BlockNumber: sd + case getStorageAt(Address, Hash, BlockNumber) + + case getCode(Address, BlockNumber) + case getBlockByHash(Hash, Bool) + case getBlockByNumber(Hash, Bool) + + /// Returns fee history with a respect to given setup + /// + /// Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. + /// The transaction will not be added to the blockchain. Note that the estimate may be significantly more + /// than the amount of gas actually used by the transaction, for a variety of reasons including EVM mechanics and node performance. + /// + /// - Parameters: + /// - UInt: Requested range of blocks. Clients will return less than the requested range if not all blocks are available. + /// - BlockNumber: Highest block of the requested range. + /// - [Double]: A monotonically increasing list of percentile values. + /// For each block in the requested range, the transactions will be sorted in ascending order + /// by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed." + case feeHistory(UInt, BlockNumber, [Double]) + + // MARK: - Additional API + /// Creates new account. + /// + /// Note: it becomes the new current unlocked account. There can only be one unlocked account at a time. + /// + /// - Parameters: + /// - String: Password for the new account. + case createAccount(String) // No in Eth API + + /// Unlocks specified account for use. + /// + /// If permanent unlocking is disabled (the default) then the duration argument will be ignored, + /// and the account will be unlocked for a single signing. + /// With permanent locking enabled, the duration sets the number of seconds to hold the account open for. + /// It will default to 300 seconds. Passing 0 unlocks the account indefinitely. + /// + /// There can only be one unlocked account at a time. + /// + /// - Parameters: + /// - Address: The address of the account to unlock. + /// - String: Passphrase to unlock the account. + /// - UInt?: Duration in seconds how long the account should remain unlocked for. + case unlockAccount(Address, String, UInt?) + case getTxPoolStatus // No in Eth API + case getTxPoolContent // No in Eth API + case getTxPoolInspect // No in Eth API +} + +extension EthJSONRPC { + var call: String { + switch self { + case .gasPrice: return "eth_gasPrice" + case .blockNumber: return "eth_blockNumber" + case .getNetwork: return "net_version" + case .getAccounts: return "eth_accounts" + case .sendRawTransaction: return "eth_sendRawTransaction" + case .sendTransaction: return "eth_sendTransaction" + case .getTransactionByHash: return "eth_getTransactionByHash" + case .getTransactionReceipt: return "eth_getTransactionReceipt" + case .personalSign: return "eth_sign" + case .getLogs: return "eth_getLogs" + case .call: return "eth_call" + case .estimateGas: return "eth_estimateGas" + case .getTransactionCount: return "eth_getTransactionCount" + case .getBalance: return "eth_getBalance" + case .getStorageAt: return "eth_getStorageAt" + case .getCode: return "eth_getCode" + case .getBlockByHash: return "eth_getBlockByHash" + case .getBlockByNumber: return "eth_getBlockByNumber" + case .feeHistory: return "eth_feeHistory" + + case .unlockAccount: return "personal_unlockAccount" + case .createAccount: return "personal_createAccount" + case .getTxPoolStatus: return "txpool_status" + case .getTxPoolContent: return "txpool_content" + case .getTxPoolInspect: return "txpool_inspect" + } + } +} + +extension EthJSONRPC { + var responseType: JRONRPCResponstType.Type { + switch self { + default: return String.self + } + } +} +extension EthJSONRPC { + var method: REST { + switch self { + default: return .POST + } + } +} + +extension EthJSONRPC { + static func sendRequest(with call: EthJSONRPC) async throws -> some JRONRPCResponstType { + switch call { + case .gasPrice: return "eth_gasPrice" + case .blockNumber: return "eth_blockNumber" + case .getNetwork: return "net_version" + case .getAccounts: return "eth_accounts" + case .sendRawTransaction: return "eth_sendRawTransaction" + case .sendTransaction: return "eth_sendTransaction" + case .getTransactionByHash: return "eth_getTransactionByHash" + case .getTransactionReceipt: return "eth_getTransactionReceipt" + case .personalSign: return "eth_sign" + case .getLogs: return "eth_getLogs" + case .call: return "eth_call" + case .estimateGas: return "eth_estimateGas" + case .getTransactionCount: return "eth_getTransactionCount" + case .getBalance: return "eth_getBalance" + case .getStorageAt: return "eth_getStorageAt" + case .getCode: return "eth_getCode" + case .getBlockByHash: return "eth_getBlockByHash" + case .getBlockByNumber: return "eth_getBlockByNumber" + case .feeHistory: return "eth_feeHistory" + + case .unlockAccount: return "personal_unlockAccount" + case .createAccount: return "personal_createAccount" + case .getTxPoolStatus: return "txpool_status" + case .getTxPoolContent: return "txpool_content" + case .getTxPoolInspect: return "txpool_inspect" + } + } +} + +private extension EthJSONRPC { + static func setupRequest(for call: EthJSONRPC) -> URLRequest { + let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! + var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) + urlRequest.httpMethod = call.method.rawValue + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") + return urlRequest + } +} + +public enum REST: String { + case POST + case GET +} + +protocol JRONRPCResponstType: Decodable { } + +extension String: JRONRPCResponstType { } + + +public enum JSONRPCmethod: String, Encodable { // 0 parameter in call case gasPrice = "eth_gasPrice" case blockNumber = "eth_blockNumber" @@ -16,7 +195,6 @@ public enum JSONRPCmethod: String, Encodable { case getTxPoolStatus = "txpool_status" case getTxPoolContent = "txpool_content" case getTxPoolInspect = "txpool_inspect" - case estimateGas = "eth_estimateGas" // 1 parameter in call case sendRawTransaction = "eth_sendRawTransaction" @@ -30,6 +208,7 @@ public enum JSONRPCmethod: String, Encodable { // 2 parameters in call case call = "eth_call" + case estimateGas = "eth_estimateGas" case getTransactionCount = "eth_getTransactionCount" case getBalance = "eth_getBalance" case getStorageAt = "eth_getStorageAt" From f1ab07d3334ccf0964099a8ac791c468f9367b64 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 24 May 2022 12:52:33 +0700 Subject: [PATCH 17/45] Method `sendRequest(with call: EthJSONRPC) async throws -> EthResponse` are now generic and error prone. It must be used as `getValue() -> T` like: `let someResponse: EthResponse = sendRequest(with: .blockNumber)` --- Sources/web3swift/Web3/Web3+Methods.swift | 127 ++++++++++++++++------ 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index 2edaa6f5c..795cac319 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -5,6 +5,7 @@ // import Foundation +import BigInt public typealias Hash = String // 32 bytes hash of block public typealias Receipt = Hash @@ -27,7 +28,7 @@ public enum EthJSONRPC { case getTransactionReceipt(Receipt) case getLogs(EventFilterParameters) case personalSign(Address, Data) - case call(EthereumTransaction) + case call(TransactionParameters) case getTransactionCount(Address, BlockNumber) case getBalance(Address, BlockNumber) @@ -118,7 +119,7 @@ extension EthJSONRPC { } extension EthJSONRPC { - var responseType: JRONRPCResponstType.Type { + var responseType: EthResponseType.Type { switch self { default: return String.self } @@ -134,44 +135,90 @@ extension EthJSONRPC { } extension EthJSONRPC { - static func sendRequest(with call: EthJSONRPC) async throws -> some JRONRPCResponstType { - switch call { - case .gasPrice: return "eth_gasPrice" - case .blockNumber: return "eth_blockNumber" - case .getNetwork: return "net_version" - case .getAccounts: return "eth_accounts" - case .sendRawTransaction: return "eth_sendRawTransaction" - case .sendTransaction: return "eth_sendTransaction" - case .getTransactionByHash: return "eth_getTransactionByHash" - case .getTransactionReceipt: return "eth_getTransactionReceipt" - case .personalSign: return "eth_sign" - case .getLogs: return "eth_getLogs" - case .call: return "eth_call" - case .estimateGas: return "eth_estimateGas" - case .getTransactionCount: return "eth_getTransactionCount" - case .getBalance: return "eth_getBalance" - case .getStorageAt: return "eth_getStorageAt" - case .getCode: return "eth_getCode" - case .getBlockByHash: return "eth_getBlockByHash" - case .getBlockByNumber: return "eth_getBlockByNumber" - case .feeHistory: return "eth_feeHistory" - - case .unlockAccount: return "personal_unlockAccount" - case .createAccount: return "personal_createAccount" - case .getTxPoolStatus: return "txpool_status" - case .getTxPoolContent: return "txpool_content" - case .getTxPoolInspect: return "txpool_inspect" + var parameters: [RPCParameter] { + switch self { + case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: + return [RPCParameter]() + case let .sendRawTransaction(hash): + return [RPCParameter.string(hash)] + case .sendTransaction(let transactionParameters): + return [RPCParameter.transaction(transactionParameters)] + case .getTransactionByHash(let hash): + return [RPCParameter.string(hash)] + case .getTransactionReceipt(let receipt): + return [RPCParameter.string(receipt)] + case .getLogs(let eventFilterParameters): + return [RPCParameter.eventFilter(eventFilterParameters)] + case .personalSign(let address, let data): + // FIXME: Add second parameter + return [RPCParameter.string(address)] + case .call(let transactionParameters): + return [RPCParameter.transaction(transactionParameters)] + case .getTransactionCount(let address, let blockNumber): + return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + case .getBalance(let address, let blockNumber): + return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + case .getStorageAt(let address, let hash, let blockNumber): + return [RPCParameter.string(address), RPCParameter.string(hash), RPCParameter.string(blockNumber.stringValue)] + case .getCode(let address, let blockNumber): + return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + case .getBlockByHash(let hash, let bool): + return [RPCParameter.string(hash), RPCParameter.bool(bool)] + case .getBlockByNumber(let hash, let bool): + return [RPCParameter.string(hash), RPCParameter.bool(bool)] + case .feeHistory(let uInt, let blockNumber, let array): + return [RPCParameter.uint(uInt), RPCParameter.string(blockNumber.stringValue), RPCParameter.doubleArray(array)] + case .createAccount(let string): + return [RPCParameter]() + case .unlockAccount(let address, let string, let optional): + return [RPCParameter]() + case .getTxPoolStatus: + return [RPCParameter]() + case .getTxPoolContent: + return [RPCParameter]() + case .getTxPoolInspect: + return [RPCParameter]() } } } +extension EthJSONRPC { + var encodedBody: Data { + let request = EthRequestBody(method: self.call, parameters: self.parameters) + // this is safe to force try this here + // Because request must failed to compile would not conformable with `Encodable` protocol + return try! JSONEncoder().encode(request) + } +} + +extension EthJSONRPC { + static func sendRequest(with call: EthJSONRPC) async throws -> EthResponse { + let request = setupRequest(for: call) + let (data, response) = try await URLSession.shared.data(for: request) + + // FIXME: Add appropriate error thrown + guard let httpResponse = response as? HTTPURLResponse, + 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } + + // FIXME: Add appropriate error thrown + guard U.self == call.responseType else { throw Web3Error.unknownError } + + // FIXME: What to do when `result` is just an hexString? + // All works here must be end at leving it string. + // Another way is to made type HexString with its own init and decode method + return try JSONDecoder().decode(EthResponse.self, from: data) + } +} + private extension EthJSONRPC { static func setupRequest(for call: EthJSONRPC) -> URLRequest { + // FIXME: Make custom url let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) - urlRequest.httpMethod = call.method.rawValue urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") + urlRequest.httpMethod = call.method.rawValue + urlRequest.httpBody = call.encodedBody return urlRequest } } @@ -181,10 +228,26 @@ public enum REST: String { case GET } -protocol JRONRPCResponstType: Decodable { } +public struct EthRequestBody: Encodable { + var jsonrpc = "2.0" + var id = Counter.increment() + + var method: String + var parameters: [RPCParameter] +} + +/// JSON RPC response structure for serialization and deserialization purposes. +public struct EthResponse: Decodable where T: EthResponseType { + public var id: Int + public var jsonrpc = "2.0" + public var result: T +} + +public protocol EthResponseType: Decodable { } -extension String: JRONRPCResponstType { } +extension BigUInt: EthResponseType { } +extension String: EthResponseType { } public enum JSONRPCmethod: String, Encodable { // 0 parameter in call From 9e0343c9c4d480082bb21a680361180551b65f94 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 24 May 2022 20:02:32 +0700 Subject: [PATCH 18/45] Rename request types - JSONRPCParameter -> APIRequestParameterType - JSONParameterElement -> APIRequestParameterElementType --- .../Promise+Web3+Eth+FeeHistory.swift | 2 +- .../Promise+Web3+Personal+UnlockAccount.swift | 2 +- .../Transaction/EthereumTransaction.swift | 4 +- Sources/web3swift/Web3/Web3+APIMethod.swift | 8 ++ ...r.swift => Web3+APIRequestParameter.swift} | 63 ++++++------ .../web3swift/Web3/Web3+InfuraProviders.swift | 8 +- Sources/web3swift/Web3/Web3+JSONRPC.swift | 2 +- Sources/web3swift/Web3/Web3+Methods.swift | 95 ++++++++++--------- .../Web3/Web3+WebsocketProvider.swift | 2 +- 9 files changed, 100 insertions(+), 86 deletions(-) create mode 100644 Sources/web3swift/Web3/Web3+APIMethod.swift rename Sources/web3swift/Web3/{Web3+JSONRPCParameter.swift => Web3+APIRequestParameter.swift} (80%) diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index efe67a81b..0a3b09ee7 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -11,7 +11,7 @@ import BigInt extension web3.Eth { func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { - let parameters: [JSONRPCParameter] = [blockCount.hexString, block, percentiles] + let parameters: [APIRequestParameterType] = [blockCount.hexString, block, percentiles] let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: parameters) let response = try await web3.dispatch(request) diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift index cae10658b..a9027eba4 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift @@ -20,7 +20,7 @@ extension web3.Personal { throw Web3Error.inputError(desc: "Can not unlock a local keystore") } - let parameters: [JSONRPCParameter] = [account.lowercased(), password, seconds] + let parameters: [APIRequestParameterType] = [account.lowercased(), password, seconds] let request = JSONRPCRequestFabric.prepareRequest(.unlockAccount, parameters: parameters) diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/web3swift/Transaction/EthereumTransaction.swift index f043cc785..e6f3b0cdc 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/web3swift/Transaction/EthereumTransaction.swift @@ -193,7 +193,7 @@ public struct EthereumTransaction: CustomStringConvertible { if method == .estimateGas || transactionOptions?.gasLimit == nil { txParams.gas = nil } - var params: [RPCParameter] = [.transaction(txParams)] + var params: [RequestParameter] = [.transaction(txParams)] if let onBlock = onBlock, method.requiredNumOfParameters == 2 { params.append(.string(onBlock)) } @@ -216,7 +216,7 @@ public struct EthereumTransaction: CustomStringConvertible { let hex = encodedData.toHexString().addHexPrefix().lowercased() var request = JSONRPCrequest() request.method = JSONRPCmethod.sendRawTransaction - let params: [RPCParameter] = [.string(hex)] + let params: [RequestParameter] = [.string(hex)] request.params = params if !request.isValid { return nil } return request diff --git a/Sources/web3swift/Web3/Web3+APIMethod.swift b/Sources/web3swift/Web3/Web3+APIMethod.swift new file mode 100644 index 000000000..319ce389a --- /dev/null +++ b/Sources/web3swift/Web3/Web3+APIMethod.swift @@ -0,0 +1,8 @@ +// +// Web3+APIMethod.swift +// Web3swift +// +// Created by Yaroslav on 24.05.2022. +// + +import Foundation diff --git a/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift b/Sources/web3swift/Web3/Web3+APIRequestParameter.swift similarity index 80% rename from Sources/web3swift/Web3/Web3+JSONRPCParameter.swift rename to Sources/web3swift/Web3/Web3+APIRequestParameter.swift index 363923275..3c23a420b 100644 --- a/Sources/web3swift/Web3/Web3+JSONRPCParameter.swift +++ b/Sources/web3swift/Web3/Web3+APIRequestParameter.swift @@ -1,6 +1,11 @@ -// Package: web3swift -// Created by Alex Vlasov. -// Copyright © 2022 Yaroslav Yashin. All rights reserved. +// +// Web3+APIRequestParameter.swift +// Web3swift +// +// Created by Yaroslav on 24.05.2022. +// + +import Foundation /// Protocol to restrict supported types which can be passed into `JSONRPCRequest` to a node. /// @@ -12,35 +17,35 @@ /// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). /// /// Please see `RPCParameter` documentation for more details. -public protocol JSONRPCParameter: Encodable { } +public protocol APIRequestParameterType: Encodable { } -protocol JSONParameterElement: Encodable { } +protocol APIRequestParameterElementType: Encodable { } -extension Int: JSONRPCParameter { } +extension Int: APIRequestParameterType { } -extension UInt: JSONRPCParameter { } +extension UInt: APIRequestParameterType { } -extension Double: JSONRPCParameter { } +extension Double: APIRequestParameterType { } -extension String: JSONRPCParameter { } +extension String: APIRequestParameterType { } -extension Bool: JSONRPCParameter { } +extension Bool: APIRequestParameterType { } -extension Array: JSONRPCParameter where Element: JSONParameterElement { } +extension Array: APIRequestParameterType where Element: APIRequestParameterElementType { } -extension TransactionParameters: JSONRPCParameter { } +extension TransactionParameters: APIRequestParameterType { } -extension EventFilterParameters: JSONRPCParameter { } +extension EventFilterParameters: APIRequestParameterType { } -extension Int: JSONParameterElement { } +extension Int: APIRequestParameterElementType { } -extension UInt: JSONParameterElement { } +extension UInt: APIRequestParameterElementType { } -extension Double: JSONParameterElement { } +extension Double: APIRequestParameterElementType { } -extension String: JSONParameterElement { } +extension String: APIRequestParameterElementType { } -extension Bool: JSONParameterElement { } +extension Bool: APIRequestParameterElementType { } /** Enum to compose request to the node params. @@ -55,11 +60,11 @@ extension Bool: JSONParameterElement { } So in our case we're using such to implement custom `encode` method to any used in node request params types. - Latter is required to encode array of `RPCParameter` to not to `[RPCParameter.int(1)]`, but to `[1]`. + Latter is required to encode array of `RequestParameter` to not to `[RequestParameter.int(1)]`, but to `[1]`. Here's an example of using this enum in field. ```swift - let jsonRPCParams: [JSONRPCParameter] = [ + let jsonRPCParams: [APIRequestParameterType] = [ .init(rawValue: 12)!, .init(rawValue: "this")!, .init(rawValue: 12.2)!, @@ -70,7 +75,7 @@ extension Bool: JSONParameterElement { } //> [12,\"this\",12.2,[12.2,12.4]]` ``` */ -public enum RPCParameter { +public enum RequestParameter { case int(Int) case intArray([Int]) @@ -85,22 +90,22 @@ public enum RPCParameter { case bool(Bool) case boolArray([Bool]) - + case transaction(TransactionParameters) case eventFilter(EventFilterParameters) } -extension RPCParameter: RawRepresentable { +extension RequestParameter: RawRepresentable { /** This init required by `RawRepresentable` protocol, which is requred to encode mixed type values array in JSON. This protocol used to implement custom `encode` method for that enum, which is encodes array of self into array of self assotiated values. - You're totally free to use explicit and more convenience member init as `RPCParameter.int(12)` in your code. + You're totally free to use explicit and more convenience member init as `RequestParameter.int(12)` in your code. */ - public init?(rawValue: JSONRPCParameter) { + public init?(rawValue: APIRequestParameterType) { /// force casting in this switch is safe because /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type // swiftlint:disable force_cast @@ -128,7 +133,7 @@ extension RPCParameter: RawRepresentable { } /// Returning associated value of the enum case. - public var rawValue: JSONRPCParameter { + public var rawValue: APIRequestParameterType { // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. switch self { case let .int(value): return value @@ -152,14 +157,14 @@ extension RPCParameter: RawRepresentable { } } -extension RPCParameter: Encodable { +extension RequestParameter: Encodable { /** - This encoder encodes `RPCParameter` assotiated value ignoring self value + This encoder encodes `RequestParameter` assotiated value ignoring self value This is required to encode mixed types array, like ```swift - let someArray: [RPCParameter] = [ + let someArray: [RequestParameter] = [ .init(rawValue: 12)!, .init(rawValue: "this")!, .init(rawValue: 12.2)!, diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index 015e26a06..d1ad0af79 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -128,7 +128,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { return socketProvider } - public func writeMessage(method: InfuraWebsocketMethod, params: [JSONRPCParameter]) throws { + public func writeMessage(method: InfuraWebsocketMethod, params: [APIRequestParameterType]) throws { let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params) let encoder = JSONEncoder() let requestData = try encoder.encode(request) @@ -136,7 +136,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { writeMessage(requestData) } - public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [JSONRPCParameter]? = nil) throws { + public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [APIRequestParameterType]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -153,7 +153,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { try setFilterAndGetChanges(method: method, params: [filterParams]) } - public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [JSONRPCParameter]? = nil) throws { + public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [APIRequestParameterType]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -204,7 +204,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { } } - public func subscribe(params: [JSONRPCParameter]) throws { + public func subscribe(params: [APIRequestParameterType]) throws { let method = InfuraWebsocketMethod.subscribe try writeMessage(method: method, params: params) } diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index 6d366d171..a16a30450 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -28,7 +28,7 @@ public struct Counter { public struct JSONRPCrequest: Encodable { public var jsonrpc: String = "2.0" public var method: JSONRPCmethod? - public var params: [RPCParameter] = [] + public var params: [RequestParameter] = [] public var id: UInt = Counter.increment() enum CodingKeys: String, CodingKey { diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index 795cac319..a9a84d56d 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -7,12 +7,13 @@ import Foundation import BigInt -public typealias Hash = String // 32 bytes hash of block +public typealias Hash = String // 32 bytes hash of block (64 chars length without 0x) public typealias Receipt = Hash -public typealias Address = Hash // 20 bytes +public typealias Address = Hash // 20 bytes (40 chars length without 0x) +public typealias TransactionHash = Hash // 64 chars length without 0x /// Ethereum JSON RPC API Calls -public enum EthJSONRPC { +public enum APIRequest { // MARK: - Official API // 0 parameter in call case gasPrice @@ -86,7 +87,7 @@ public enum EthJSONRPC { case getTxPoolInspect // No in Eth API } -extension EthJSONRPC { +extension APIRequest { var call: String { switch self { case .gasPrice: return "eth_gasPrice" @@ -118,81 +119,81 @@ extension EthJSONRPC { } } -extension EthJSONRPC { - var responseType: EthResponseType.Type { +extension APIRequest { + public var responseType: APIResponseType.Type { switch self { default: return String.self } } } -extension EthJSONRPC { - var method: REST { +extension APIRequest { + public var method: REST { switch self { default: return .POST } } } -extension EthJSONRPC { - var parameters: [RPCParameter] { +extension APIRequest { + var parameters: [RequestParameter] { switch self { case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: - return [RPCParameter]() + return [RequestParameter]() case let .sendRawTransaction(hash): - return [RPCParameter.string(hash)] + return [RequestParameter.string(hash)] case .sendTransaction(let transactionParameters): - return [RPCParameter.transaction(transactionParameters)] + return [RequestParameter.transaction(transactionParameters)] case .getTransactionByHash(let hash): - return [RPCParameter.string(hash)] + return [RequestParameter.string(hash)] case .getTransactionReceipt(let receipt): - return [RPCParameter.string(receipt)] + return [RequestParameter.string(receipt)] case .getLogs(let eventFilterParameters): - return [RPCParameter.eventFilter(eventFilterParameters)] + return [RequestParameter.eventFilter(eventFilterParameters)] case .personalSign(let address, let data): // FIXME: Add second parameter - return [RPCParameter.string(address)] + return [RequestParameter.string(address)] case .call(let transactionParameters): - return [RPCParameter.transaction(transactionParameters)] + return [RequestParameter.transaction(transactionParameters)] case .getTransactionCount(let address, let blockNumber): - return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] case .getBalance(let address, let blockNumber): - return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] case .getStorageAt(let address, let hash, let blockNumber): - return [RPCParameter.string(address), RPCParameter.string(hash), RPCParameter.string(blockNumber.stringValue)] + return [RequestParameter.string(address), RequestParameter.string(hash), RequestParameter.string(blockNumber.stringValue)] case .getCode(let address, let blockNumber): - return [RPCParameter.string(address), RPCParameter.string(blockNumber.stringValue)] + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] case .getBlockByHash(let hash, let bool): - return [RPCParameter.string(hash), RPCParameter.bool(bool)] + return [RequestParameter.string(hash), RequestParameter.bool(bool)] case .getBlockByNumber(let hash, let bool): - return [RPCParameter.string(hash), RPCParameter.bool(bool)] + return [RequestParameter.string(hash), RequestParameter.bool(bool)] case .feeHistory(let uInt, let blockNumber, let array): - return [RPCParameter.uint(uInt), RPCParameter.string(blockNumber.stringValue), RPCParameter.doubleArray(array)] + return [RequestParameter.uint(uInt), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] case .createAccount(let string): - return [RPCParameter]() + return [RequestParameter]() case .unlockAccount(let address, let string, let optional): - return [RPCParameter]() + return [RequestParameter]() case .getTxPoolStatus: - return [RPCParameter]() + return [RequestParameter]() case .getTxPoolContent: - return [RPCParameter]() + return [RequestParameter]() case .getTxPoolInspect: - return [RPCParameter]() + return [RequestParameter]() } } } -extension EthJSONRPC { +extension APIRequest { var encodedBody: Data { - let request = EthRequestBody(method: self.call, parameters: self.parameters) + let request = RequestBody(method: self.call, parameters: self.parameters) // this is safe to force try this here // Because request must failed to compile would not conformable with `Encodable` protocol return try! JSONEncoder().encode(request) } } -extension EthJSONRPC { - static func sendRequest(with call: EthJSONRPC) async throws -> EthResponse { +extension APIRequest { + public static func sendRequest(with call: APIRequest) async throws -> APIResponse { let request = setupRequest(for: call) let (data, response) = try await URLSession.shared.data(for: request) @@ -206,12 +207,12 @@ extension EthJSONRPC { // FIXME: What to do when `result` is just an hexString? // All works here must be end at leving it string. // Another way is to made type HexString with its own init and decode method - return try JSONDecoder().decode(EthResponse.self, from: data) + return try JSONDecoder().decode(APIResponse.self, from: data) } } -private extension EthJSONRPC { - static func setupRequest(for call: EthJSONRPC) -> URLRequest { +private extension APIRequest { + static func setupRequest(for call: APIRequest) -> URLRequest { // FIXME: Make custom url let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) @@ -228,26 +229,26 @@ public enum REST: String { case GET } -public struct EthRequestBody: Encodable { +public struct RequestBody: Encodable { var jsonrpc = "2.0" var id = Counter.increment() var method: String - var parameters: [RPCParameter] + var parameters: [RequestParameter] } /// JSON RPC response structure for serialization and deserialization purposes. -public struct EthResponse: Decodable where T: EthResponseType { +public struct APIResponse: Decodable where T: APIResponseType { public var id: Int public var jsonrpc = "2.0" public var result: T } -public protocol EthResponseType: Decodable { } +public protocol APIResponseType: Decodable { } -extension BigUInt: EthResponseType { } +extension BigUInt: APIResponseType { } -extension String: EthResponseType { } +extension String: APIResponseType { } public enum JSONRPCmethod: String, Encodable { // 0 parameter in call @@ -317,17 +318,17 @@ public enum JSONRPCmethod: String, Encodable { } public struct JSONRPCRequestFabric { - public static func prepareRequest(_ method: JSONRPCmethod, parameters: [JSONRPCParameter]) -> JSONRPCrequest { + public static func prepareRequest(_ method: JSONRPCmethod, parameters: [APIRequestParameterType]) -> JSONRPCrequest { var request = JSONRPCrequest() request.method = method - request.params = parameters.compactMap { RPCParameter.init(rawValue: $0) } + request.params = parameters.compactMap { RequestParameter.init(rawValue: $0) } return request } - public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [JSONRPCParameter]) -> InfuraWebsocketRequest { + public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [APIRequestParameterType]) -> InfuraWebsocketRequest { var request = InfuraWebsocketRequest() request.method = method - request.params = parameters.compactMap { RPCParameter.init(rawValue: $0) } + request.params = parameters.compactMap { RequestParameter.init(rawValue: $0) } return request } } diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index c9dacc027..73093bcde 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -56,7 +56,7 @@ public enum InfuraWebsocketMethod: String, Encodable { public struct InfuraWebsocketRequest: Encodable { public var jsonrpc: String = "2.0" public var method: InfuraWebsocketMethod? - public var params: [RPCParameter] = [] + public var params: [RequestParameter] = [] public var id = Counter.increment() enum CodingKeys: String, CodingKey { From 5db22723e69204a8f64863552dc73ad565ca374b Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 25 May 2022 18:32:32 +0700 Subject: [PATCH 19/45] Implement most of required protocols to make decoding responses to generic implementation. There's follow types presented: - enum `APIRequest` - main type that user should be working with. - `APIResponse` - type that returns network request method on successfully API call, where generic `T` type is the any given value of `result`. - protocol `APIResponseType` - protocol that must conforms any possible `result` type. - protocol `LiteralInitableFromString` - protocol that conforms any `Numeric` literals that `result` property hols as `String`. - protocol `IntegerInitableWithRadix` - utility protocol that conforms any `Integer` literals that have follow initializee: `init?(from hexString: String)` --- .../web3swift/API/HexDecodableProtocols.swift | 59 +++++ Sources/web3swift/API/Web3+APIMethod.swift | 242 +++++++++++++++++ .../Web3+APIRequestParameter.swift | 0 Sources/web3swift/Web3/Web3+APIMethod.swift | 8 - Sources/web3swift/Web3/Web3+Methods.swift | 250 +----------------- 5 files changed, 305 insertions(+), 254 deletions(-) create mode 100644 Sources/web3swift/API/HexDecodableProtocols.swift create mode 100644 Sources/web3swift/API/Web3+APIMethod.swift rename Sources/web3swift/{Web3 => API}/Web3+APIRequestParameter.swift (100%) delete mode 100644 Sources/web3swift/Web3/Web3+APIMethod.swift diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/web3swift/API/HexDecodableProtocols.swift new file mode 100644 index 000000000..65b6cd5ea --- /dev/null +++ b/Sources/web3swift/API/HexDecodableProtocols.swift @@ -0,0 +1,59 @@ +// +// HexDecodableProtocols.swift +// Web3swift +// +// Created by Yaroslav on 25.05.2022. +// + +import BigInt + +/// This is utility protocol for decoding API Responses +/// +/// You better not use it in any other part of a bit of code except `APIResponse` decoding. +/// +/// This protocols intention is to work around that Ethereum API cases, when almost all numbers are comming as strings. +/// More than that their notation (e.g. 0x12d) are don't fit with the default Numeric decoders behaviours. +/// So to work around that for generic cases we're going to force decode `APIResponse.result` field as `String` +/// and then initiate it +public protocol LiteralInitableFromString: APIResponseType { + init?(from hexString: String) +} + +extension LiteralInitableFromString where Self: IntegerInitableWithRadix { + /// This initializer is intended to init `(U)Int` from hex string with `0x` prefix. + public init?(from hexString: String) { + guard hexString.hasPrefix("0x") else { return nil } + let tmpString = String(hexString.dropFirst(2)) + guard let value = Self(tmpString, radix: 16) else { return nil } + self = value + } +} + +extension Int: LiteralInitableFromString { } + +extension UInt: LiteralInitableFromString { } + +extension BigInt: LiteralInitableFromString { } + +extension BigUInt: LiteralInitableFromString { } + +extension String: LiteralInitableFromString { + public init?(from hexString: String) { + self = hexString + } +} + + +// ------ +public protocol IntegerInitableWithRadix { + init?(_ text: S, radix: Int) +} + +extension Int: IntegerInitableWithRadix { } + +extension UInt: IntegerInitableWithRadix { } + +extension BigInt: IntegerInitableWithRadix { } + +extension BigUInt: IntegerInitableWithRadix { } +// ------ diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift new file mode 100644 index 000000000..ae18d1eb2 --- /dev/null +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -0,0 +1,242 @@ +// +// Web3+APIMethod.swift +// Web3swift +// +// Created by Yaroslav on 24.05.2022. +// + +import Foundation + +public protocol APIResponseType: Decodable { } + +public typealias Hash = String // 32 bytes hash of block (64 chars length without 0x) +public typealias Receipt = Hash +public typealias Address = Hash // 20 bytes (40 chars length without 0x) +public typealias TransactionHash = Hash // 64 chars length without 0x + +/// Ethereum JSON RPC API Calls +public enum APIRequest { + // MARK: - Official API + // 0 parameter in call + case gasPrice + case blockNumber + case getNetwork + case getAccounts + // ?? + case estimateGas + + case sendRawTransaction(Hash) + case sendTransaction(TransactionParameters) + case getTransactionByHash(Hash) + case getTransactionReceipt(Receipt) + case getLogs(EventFilterParameters) + case personalSign(Address, Data) + case call(TransactionParameters) + case getTransactionCount(Address, BlockNumber) + case getBalance(Address, BlockNumber) + + /// Returns the value from a storage position at a given address. + /// + /// - Parameters: + /// - Address: Address + /// - Storage: slot + /// - BlockNumber: sd + case getStorageAt(Address, Hash, BlockNumber) + + case getCode(Address, BlockNumber) + case getBlockByHash(Hash, Bool) + case getBlockByNumber(Hash, Bool) + + /// Returns fee history with a respect to given setup + /// + /// Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. + /// The transaction will not be added to the blockchain. Note that the estimate may be significantly more + /// than the amount of gas actually used by the transaction, for a variety of reasons including EVM mechanics and node performance. + /// + /// - Parameters: + /// - UInt: Requested range of blocks. Clients will return less than the requested range if not all blocks are available. + /// - BlockNumber: Highest block of the requested range. + /// - [Double]: A monotonically increasing list of percentile values. + /// For each block in the requested range, the transactions will be sorted in ascending order + /// by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed." + case feeHistory(UInt, BlockNumber, [Double]) + + // MARK: - Additional API + /// Creates new account. + /// + /// Note: it becomes the new current unlocked account. There can only be one unlocked account at a time. + /// + /// - Parameters: + /// - String: Password for the new account. + case createAccount(String) // No in Eth API + + /// Unlocks specified account for use. + /// + /// If permanent unlocking is disabled (the default) then the duration argument will be ignored, + /// and the account will be unlocked for a single signing. + /// With permanent locking enabled, the duration sets the number of seconds to hold the account open for. + /// It will default to 300 seconds. Passing 0 unlocks the account indefinitely. + /// + /// There can only be one unlocked account at a time. + /// + /// - Parameters: + /// - Address: The address of the account to unlock. + /// - String: Passphrase to unlock the account. + /// - UInt?: Duration in seconds how long the account should remain unlocked for. + case unlockAccount(Address, String, UInt?) + case getTxPoolStatus // No in Eth API + case getTxPoolContent // No in Eth API + case getTxPoolInspect // No in Eth API +} + +extension APIRequest { + public var method: REST { + switch self { + default: return .POST + } + } + + public var responseType: APIResponseType.Type { + switch self { + case .blockNumber: return UInt.self + default: return String.self + } + } + + var encodedBody: Data { + let request = RequestBody(method: self.call, parameters: self.parameters) + // this is safe to force try this here + // Because request must failed to compile if it not conformable with `Encodable` protocol + return try! JSONEncoder().encode(request) + } + + var parameters: [RequestParameter] { + switch self { + case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: + return [RequestParameter]() + case let .sendRawTransaction(hash): + return [RequestParameter.string(hash)] + case .sendTransaction(let transactionParameters): + return [RequestParameter.transaction(transactionParameters)] + case .getTransactionByHash(let hash): + return [RequestParameter.string(hash)] + case .getTransactionReceipt(let receipt): + return [RequestParameter.string(receipt)] + case .getLogs(let eventFilterParameters): + return [RequestParameter.eventFilter(eventFilterParameters)] + case .personalSign(let address, let data): + // FIXME: Add second parameter + return [RequestParameter.string(address)] + case .call(let transactionParameters): + return [RequestParameter.transaction(transactionParameters)] + case .getTransactionCount(let address, let blockNumber): + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getBalance(let address, let blockNumber): + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getStorageAt(let address, let hash, let blockNumber): + return [RequestParameter.string(address), RequestParameter.string(hash), RequestParameter.string(blockNumber.stringValue)] + case .getCode(let address, let blockNumber): + return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getBlockByHash(let hash, let bool): + return [RequestParameter.string(hash), RequestParameter.bool(bool)] + case .getBlockByNumber(let hash, let bool): + return [RequestParameter.string(hash), RequestParameter.bool(bool)] + case .feeHistory(let uInt, let blockNumber, let array): + return [RequestParameter.uint(uInt), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] + case .createAccount(let string): + return [RequestParameter]() + case .unlockAccount(let address, let string, let optional): + return [RequestParameter]() + case .getTxPoolStatus: + return [RequestParameter]() + case .getTxPoolContent: + return [RequestParameter]() + case .getTxPoolInspect: + return [RequestParameter]() + } + } + + var call: String { + switch self { + case .gasPrice: return "eth_gasPrice" + case .blockNumber: return "eth_blockNumber" + case .getNetwork: return "net_version" + case .getAccounts: return "eth_accounts" + case .sendRawTransaction: return "eth_sendRawTransaction" + case .sendTransaction: return "eth_sendTransaction" + case .getTransactionByHash: return "eth_getTransactionByHash" + case .getTransactionReceipt: return "eth_getTransactionReceipt" + case .personalSign: return "eth_sign" + case .getLogs: return "eth_getLogs" + case .call: return "eth_call" + case .estimateGas: return "eth_estimateGas" + case .getTransactionCount: return "eth_getTransactionCount" + case .getBalance: return "eth_getBalance" + case .getStorageAt: return "eth_getStorageAt" + case .getCode: return "eth_getCode" + case .getBlockByHash: return "eth_getBlockByHash" + case .getBlockByNumber: return "eth_getBlockByNumber" + case .feeHistory: return "eth_feeHistory" + + case .unlockAccount: return "personal_unlockAccount" + case .createAccount: return "personal_createAccount" + case .getTxPoolStatus: return "txpool_status" + case .getTxPoolContent: return "txpool_content" + case .getTxPoolInspect: return "txpool_inspect" + } + } +} + +extension APIRequest { + public static func sendRequest(with call: APIRequest) async throws -> APIResponse { + /// Don't even try to make network request if the U type dosen't equal to supposed by API + // FIXME: Add appropriate error thrown + guard U.self == call.responseType else { throw Web3Error.unknownError } + + let request = setupRequest(for: call) + let (data, response) = try await URLSession.shared.data(for: request) + + // FIXME: Add appropriate error thrown + guard let httpResponse = response as? HTTPURLResponse, + 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } + + if U.self == UInt.self || U.self == Int.self || U.self == BigInt.self || U.self == BigUInt.self { + let some = try! JSONDecoder().decode(APIResponse.self, from: data) + // FIXME: Add appropriate error thrown. + guard let tmpAnother = U(from: some.result) else { throw Web3Error.unknownError } + return APIResponse(id: some.id, jsonrpc: some.jsonrpc, result: tmpAnother) + } + return try JSONDecoder().decode(APIResponse.self, from: data) + } + + static func setupRequest(for call: APIRequest) -> URLRequest { + // FIXME: Make custom url + let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! + var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") + urlRequest.httpMethod = call.method.rawValue + urlRequest.httpBody = call.encodedBody + return urlRequest + } +} + +public enum REST: String { + case POST + case GET +} + +public struct RequestBody: Encodable { + var jsonrpc = "2.0" + var id = Counter.increment() + + var method: String + var parameters: [RequestParameter] +} + +/// JSON RPC response structure for serialization and deserialization purposes. +public struct APIResponse: Decodable where T: LiteralInitableFromString { + public var id: Int + public var jsonrpc = "2.0" + public var result: T +} diff --git a/Sources/web3swift/Web3/Web3+APIRequestParameter.swift b/Sources/web3swift/API/Web3+APIRequestParameter.swift similarity index 100% rename from Sources/web3swift/Web3/Web3+APIRequestParameter.swift rename to Sources/web3swift/API/Web3+APIRequestParameter.swift diff --git a/Sources/web3swift/Web3/Web3+APIMethod.swift b/Sources/web3swift/Web3/Web3+APIMethod.swift deleted file mode 100644 index 319ce389a..000000000 --- a/Sources/web3swift/Web3/Web3+APIMethod.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// Web3+APIMethod.swift -// Web3swift -// -// Created by Yaroslav on 24.05.2022. -// - -import Foundation diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift index a9a84d56d..51b5cfe98 100755 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ b/Sources/web3swift/Web3/Web3+Methods.swift @@ -1,255 +1,13 @@ -// web3swift // -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. +// Web3+APIMethod.swift +// Web3swift +// +// Created by Yaroslav on 24.05.2022. // import Foundation import BigInt -public typealias Hash = String // 32 bytes hash of block (64 chars length without 0x) -public typealias Receipt = Hash -public typealias Address = Hash // 20 bytes (40 chars length without 0x) -public typealias TransactionHash = Hash // 64 chars length without 0x - -/// Ethereum JSON RPC API Calls -public enum APIRequest { - // MARK: - Official API - // 0 parameter in call - case gasPrice - case blockNumber - case getNetwork - case getAccounts - // ?? - case estimateGas - - case sendRawTransaction(Hash) - case sendTransaction(TransactionParameters) - case getTransactionByHash(Hash) - case getTransactionReceipt(Receipt) - case getLogs(EventFilterParameters) - case personalSign(Address, Data) - case call(TransactionParameters) - case getTransactionCount(Address, BlockNumber) - case getBalance(Address, BlockNumber) - - /// Returns the value from a storage position at a given address. - /// - /// - Parameters: - /// - Address: Address - /// - Storage: slot - /// - BlockNumber: sd - case getStorageAt(Address, Hash, BlockNumber) - - case getCode(Address, BlockNumber) - case getBlockByHash(Hash, Bool) - case getBlockByNumber(Hash, Bool) - - /// Returns fee history with a respect to given setup - /// - /// Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. - /// The transaction will not be added to the blockchain. Note that the estimate may be significantly more - /// than the amount of gas actually used by the transaction, for a variety of reasons including EVM mechanics and node performance. - /// - /// - Parameters: - /// - UInt: Requested range of blocks. Clients will return less than the requested range if not all blocks are available. - /// - BlockNumber: Highest block of the requested range. - /// - [Double]: A monotonically increasing list of percentile values. - /// For each block in the requested range, the transactions will be sorted in ascending order - /// by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed." - case feeHistory(UInt, BlockNumber, [Double]) - - // MARK: - Additional API - /// Creates new account. - /// - /// Note: it becomes the new current unlocked account. There can only be one unlocked account at a time. - /// - /// - Parameters: - /// - String: Password for the new account. - case createAccount(String) // No in Eth API - - /// Unlocks specified account for use. - /// - /// If permanent unlocking is disabled (the default) then the duration argument will be ignored, - /// and the account will be unlocked for a single signing. - /// With permanent locking enabled, the duration sets the number of seconds to hold the account open for. - /// It will default to 300 seconds. Passing 0 unlocks the account indefinitely. - /// - /// There can only be one unlocked account at a time. - /// - /// - Parameters: - /// - Address: The address of the account to unlock. - /// - String: Passphrase to unlock the account. - /// - UInt?: Duration in seconds how long the account should remain unlocked for. - case unlockAccount(Address, String, UInt?) - case getTxPoolStatus // No in Eth API - case getTxPoolContent // No in Eth API - case getTxPoolInspect // No in Eth API -} - -extension APIRequest { - var call: String { - switch self { - case .gasPrice: return "eth_gasPrice" - case .blockNumber: return "eth_blockNumber" - case .getNetwork: return "net_version" - case .getAccounts: return "eth_accounts" - case .sendRawTransaction: return "eth_sendRawTransaction" - case .sendTransaction: return "eth_sendTransaction" - case .getTransactionByHash: return "eth_getTransactionByHash" - case .getTransactionReceipt: return "eth_getTransactionReceipt" - case .personalSign: return "eth_sign" - case .getLogs: return "eth_getLogs" - case .call: return "eth_call" - case .estimateGas: return "eth_estimateGas" - case .getTransactionCount: return "eth_getTransactionCount" - case .getBalance: return "eth_getBalance" - case .getStorageAt: return "eth_getStorageAt" - case .getCode: return "eth_getCode" - case .getBlockByHash: return "eth_getBlockByHash" - case .getBlockByNumber: return "eth_getBlockByNumber" - case .feeHistory: return "eth_feeHistory" - - case .unlockAccount: return "personal_unlockAccount" - case .createAccount: return "personal_createAccount" - case .getTxPoolStatus: return "txpool_status" - case .getTxPoolContent: return "txpool_content" - case .getTxPoolInspect: return "txpool_inspect" - } - } -} - -extension APIRequest { - public var responseType: APIResponseType.Type { - switch self { - default: return String.self - } - } -} - -extension APIRequest { - public var method: REST { - switch self { - default: return .POST - } - } -} - -extension APIRequest { - var parameters: [RequestParameter] { - switch self { - case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: - return [RequestParameter]() - case let .sendRawTransaction(hash): - return [RequestParameter.string(hash)] - case .sendTransaction(let transactionParameters): - return [RequestParameter.transaction(transactionParameters)] - case .getTransactionByHash(let hash): - return [RequestParameter.string(hash)] - case .getTransactionReceipt(let receipt): - return [RequestParameter.string(receipt)] - case .getLogs(let eventFilterParameters): - return [RequestParameter.eventFilter(eventFilterParameters)] - case .personalSign(let address, let data): - // FIXME: Add second parameter - return [RequestParameter.string(address)] - case .call(let transactionParameters): - return [RequestParameter.transaction(transactionParameters)] - case .getTransactionCount(let address, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] - case .getBalance(let address, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] - case .getStorageAt(let address, let hash, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(hash), RequestParameter.string(blockNumber.stringValue)] - case .getCode(let address, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] - case .getBlockByHash(let hash, let bool): - return [RequestParameter.string(hash), RequestParameter.bool(bool)] - case .getBlockByNumber(let hash, let bool): - return [RequestParameter.string(hash), RequestParameter.bool(bool)] - case .feeHistory(let uInt, let blockNumber, let array): - return [RequestParameter.uint(uInt), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] - case .createAccount(let string): - return [RequestParameter]() - case .unlockAccount(let address, let string, let optional): - return [RequestParameter]() - case .getTxPoolStatus: - return [RequestParameter]() - case .getTxPoolContent: - return [RequestParameter]() - case .getTxPoolInspect: - return [RequestParameter]() - } - } -} - -extension APIRequest { - var encodedBody: Data { - let request = RequestBody(method: self.call, parameters: self.parameters) - // this is safe to force try this here - // Because request must failed to compile would not conformable with `Encodable` protocol - return try! JSONEncoder().encode(request) - } -} - -extension APIRequest { - public static func sendRequest(with call: APIRequest) async throws -> APIResponse { - let request = setupRequest(for: call) - let (data, response) = try await URLSession.shared.data(for: request) - - // FIXME: Add appropriate error thrown - guard let httpResponse = response as? HTTPURLResponse, - 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } - - // FIXME: Add appropriate error thrown - guard U.self == call.responseType else { throw Web3Error.unknownError } - - // FIXME: What to do when `result` is just an hexString? - // All works here must be end at leving it string. - // Another way is to made type HexString with its own init and decode method - return try JSONDecoder().decode(APIResponse.self, from: data) - } -} - -private extension APIRequest { - static func setupRequest(for call: APIRequest) -> URLRequest { - // FIXME: Make custom url - let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! - var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) - urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") - urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") - urlRequest.httpMethod = call.method.rawValue - urlRequest.httpBody = call.encodedBody - return urlRequest - } -} - -public enum REST: String { - case POST - case GET -} - -public struct RequestBody: Encodable { - var jsonrpc = "2.0" - var id = Counter.increment() - - var method: String - var parameters: [RequestParameter] -} - -/// JSON RPC response structure for serialization and deserialization purposes. -public struct APIResponse: Decodable where T: APIResponseType { - public var id: Int - public var jsonrpc = "2.0" - public var result: T -} - -public protocol APIResponseType: Decodable { } - -extension BigUInt: APIResponseType { } - -extension String: APIResponseType { } - public enum JSONRPCmethod: String, Encodable { // 0 parameter in call case gasPrice = "eth_gasPrice" From 245cc0d63dc84cc4d0787aeda300cce8edfc943b Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 25 May 2022 20:14:51 +0700 Subject: [PATCH 20/45] Make `APIRequestParameterType` internal. This types uses to encode all given attributes to heterogeneous array, so it should not be public. --- .../API/Web3+APIRequestParameter.swift | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Sources/web3swift/API/Web3+APIRequestParameter.swift b/Sources/web3swift/API/Web3+APIRequestParameter.swift index 3c23a420b..163bc067c 100644 --- a/Sources/web3swift/API/Web3+APIRequestParameter.swift +++ b/Sources/web3swift/API/Web3+APIRequestParameter.swift @@ -7,17 +7,15 @@ import Foundation -/// Protocol to restrict supported types which can be passed into `JSONRPCRequest` to a node. -/// -/// You **must not** conform any type to that protocol. +/// Protocol to restrict supported types which can be passed into `RequestParameter` to a node. /// /// Due to internal logic and swift itself restrictions, there's lack of encoding generic types -/// so current implementation of `JSONRPCParameter`s belongs on hardcoded supported types. +/// so current implementation of `RequestParameter`s belongs on hardcoded supported types. /// /// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). /// -/// Please see `RPCParameter` documentation for more details. -public protocol APIRequestParameterType: Encodable { } +/// Please see `RequestParameter` documentation for more details. +protocol APIRequestParameterType: Encodable { } protocol APIRequestParameterElementType: Encodable { } @@ -75,7 +73,7 @@ extension Bool: APIRequestParameterElementType { } //> [12,\"this\",12.2,[12.2,12.4]]` ``` */ -public enum RequestParameter { +enum RequestParameter { case int(Int) case intArray([Int]) @@ -105,7 +103,7 @@ extension RequestParameter: RawRepresentable { You're totally free to use explicit and more convenience member init as `RequestParameter.int(12)` in your code. */ - public init?(rawValue: APIRequestParameterType) { + init?(rawValue: APIRequestParameterType) { /// force casting in this switch is safe because /// each `rawValue` forced to casts only in exact case which is runs based on `rawValues` type // swiftlint:disable force_cast @@ -133,7 +131,7 @@ extension RequestParameter: RawRepresentable { } /// Returning associated value of the enum case. - public var rawValue: APIRequestParameterType { + var rawValue: APIRequestParameterType { // cases can't be merged, coz it cause compiler error since it couldn't predict what exact type on exact case will be returned. switch self { case let .int(value): return value @@ -175,7 +173,7 @@ extension RequestParameter: Encodable { //> [12,\"this\",12.2,[12.2,12.4]]` ``` */ - public func encode(to encoder: Encoder) throws { + func encode(to encoder: Encoder) throws { var enumContainer = encoder.singleValueContainer() /// force casting in this switch is safe because /// each `rawValue` forced to casts only in exact case which is runs based on `rawValue` type From 2a54eec163a789eca35893b72aae605eb3e72374 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 26 May 2022 12:14:48 +0700 Subject: [PATCH 21/45] Refactor API a bit. --- .../web3swift/API/HexDecodableProtocols.swift | 30 ++++++----- Sources/web3swift/API/Web3+APIMethod.swift | 51 ++++++++++--------- .../API/Web3+APIRequestParameter.swift | 2 - 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/web3swift/API/HexDecodableProtocols.swift index 65b6cd5ea..1262a247e 100644 --- a/Sources/web3swift/API/HexDecodableProtocols.swift +++ b/Sources/web3swift/API/HexDecodableProtocols.swift @@ -7,6 +7,12 @@ import BigInt +public protocol APIResultType: Decodable { } + +extension Array: APIResultType where Element: APIResultType { } + +extension String: APIResultType { } + /// This is utility protocol for decoding API Responses /// /// You better not use it in any other part of a bit of code except `APIResponse` decoding. @@ -15,11 +21,11 @@ import BigInt /// More than that their notation (e.g. 0x12d) are don't fit with the default Numeric decoders behaviours. /// So to work around that for generic cases we're going to force decode `APIResponse.result` field as `String` /// and then initiate it -public protocol LiteralInitableFromString: APIResponseType { +public protocol LiteralInitiableFromString: APIResultType { init?(from hexString: String) } -extension LiteralInitableFromString where Self: IntegerInitableWithRadix { +extension LiteralInitiableFromString where Self: IntegerInitableWithRadix { /// This initializer is intended to init `(U)Int` from hex string with `0x` prefix. public init?(from hexString: String) { guard hexString.hasPrefix("0x") else { return nil } @@ -29,22 +35,21 @@ extension LiteralInitableFromString where Self: IntegerInitableWithRadix { } } -extension Int: LiteralInitableFromString { } -extension UInt: LiteralInitableFromString { } +extension Int: LiteralInitiableFromString { } -extension BigInt: LiteralInitableFromString { } +extension UInt: LiteralInitiableFromString { } -extension BigUInt: LiteralInitableFromString { } +extension BigInt: LiteralInitiableFromString { } -extension String: LiteralInitableFromString { - public init?(from hexString: String) { - self = hexString - } -} +extension BigUInt: LiteralInitiableFromString { } +// This don't work without each other. +//extension LiteralInitiableFromString { +// public init?(from hexString: String) { return nil } +//} +//extension Array: LiteralInitiableFromString where Element: LiteralInitiableFromString { } -// ------ public protocol IntegerInitableWithRadix { init?(_ text: S, radix: Int) } @@ -56,4 +61,3 @@ extension UInt: IntegerInitableWithRadix { } extension BigInt: IntegerInitableWithRadix { } extension BigUInt: IntegerInitableWithRadix { } -// ------ diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift index ae18d1eb2..f5bb826ed 100644 --- a/Sources/web3swift/API/Web3+APIMethod.swift +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -6,8 +6,7 @@ // import Foundation - -public protocol APIResponseType: Decodable { } +import BigInt public typealias Hash = String // 32 bytes hash of block (64 chars length without 0x) public typealias Receipt = Hash @@ -96,15 +95,17 @@ extension APIRequest { } } - public var responseType: APIResponseType.Type { + public var responseType: APIResultType.Type { switch self { case .blockNumber: return UInt.self + case .getAccounts: return [EthereumAddress].self + case .feeHistory: return Web3.Oracle.FeeHistory.self default: return String.self } } var encodedBody: Data { - let request = RequestBody(method: self.call, parameters: self.parameters) + let request = RequestBody(method: self.call, params: self.parameters) // this is safe to force try this here // Because request must failed to compile if it not conformable with `Encodable` protocol return try! JSONEncoder().encode(request) @@ -142,7 +143,7 @@ extension APIRequest { case .getBlockByNumber(let hash, let bool): return [RequestParameter.string(hash), RequestParameter.bool(bool)] case .feeHistory(let uInt, let blockNumber, let array): - return [RequestParameter.uint(uInt), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] + return [RequestParameter.string(uInt.hexString), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] case .createAccount(let string): return [RequestParameter]() case .unlockAccount(let address, let string, let optional): @@ -188,31 +189,35 @@ extension APIRequest { } extension APIRequest { - public static func sendRequest(with call: APIRequest) async throws -> APIResponse { - /// Don't even try to make network request if the U type dosen't equal to supposed by API + public static func sendRequest(with provider: Web3Provider, for call: APIRequest) async throws -> APIResponse { + /// Don't even try to make network request if the `Result` type dosen't equal to supposed by API // FIXME: Add appropriate error thrown - guard U.self == call.responseType else { throw Web3Error.unknownError } + guard Result.self == call.responseType else { throw Web3Error.unknownError } - let request = setupRequest(for: call) - let (data, response) = try await URLSession.shared.data(for: request) + let request = setupRequest(for: call, with: provider) + let (data, response) = try await provider.session.data(for: request) // FIXME: Add appropriate error thrown guard let httpResponse = response as? HTTPURLResponse, 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } - if U.self == UInt.self || U.self == Int.self || U.self == BigInt.self || U.self == BigUInt.self { - let some = try! JSONDecoder().decode(APIResponse.self, from: data) + if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { + /// This types for sure conformed with `LiteralInitiableFromString` + // FIXME: Make appropriate error + guard let U = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.unknownError} + let responseAsString = try! JSONDecoder().decode(APIResponse.self, from: data) // FIXME: Add appropriate error thrown. - guard let tmpAnother = U(from: some.result) else { throw Web3Error.unknownError } - return APIResponse(id: some.id, jsonrpc: some.jsonrpc, result: tmpAnother) + guard let literalValue = U.init(from: responseAsString.result) else { throw Web3Error.unknownError } + /// `U` is a APIResponseType type, which `LiteralInitiableFromString` conforms to, so it is safe to cast that. + // FIXME: Make appropriate error + guard let asT = literalValue as? Result else { throw Web3Error.unknownError } + return APIResponse(id: responseAsString.id, jsonrpc: responseAsString.jsonrpc, result: asT) } - return try JSONDecoder().decode(APIResponse.self, from: data) + return try JSONDecoder().decode(APIResponse.self, from: data) } - static func setupRequest(for call: APIRequest) -> URLRequest { - // FIXME: Make custom url - let url = URL(string: "https://mainnet.infura.io/v3/4406c3acf862426c83991f1752c46dd8")! - var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) + static func setupRequest(for call: APIRequest, with provider: Web3Provider) -> URLRequest { + var urlRequest = URLRequest(url: provider.url, cachePolicy: .reloadIgnoringCacheData) urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") urlRequest.httpMethod = call.method.rawValue @@ -226,17 +231,17 @@ public enum REST: String { case GET } -public struct RequestBody: Encodable { +struct RequestBody: Encodable { var jsonrpc = "2.0" var id = Counter.increment() var method: String - var parameters: [RequestParameter] + var params: [RequestParameter] } /// JSON RPC response structure for serialization and deserialization purposes. -public struct APIResponse: Decodable where T: LiteralInitableFromString { +public struct APIResponse: Decodable where Result: APIResultType { public var id: Int public var jsonrpc = "2.0" - public var result: T + public var result: Result } diff --git a/Sources/web3swift/API/Web3+APIRequestParameter.swift b/Sources/web3swift/API/Web3+APIRequestParameter.swift index 163bc067c..d16981a81 100644 --- a/Sources/web3swift/API/Web3+APIRequestParameter.swift +++ b/Sources/web3swift/API/Web3+APIRequestParameter.swift @@ -12,8 +12,6 @@ import Foundation /// Due to internal logic and swift itself restrictions, there's lack of encoding generic types /// so current implementation of `RequestParameter`s belongs on hardcoded supported types. /// -/// Conformance of that protocol by a custom type will be silently failed to encode (e.g. there won't be in request). -/// /// Please see `RequestParameter` documentation for more details. protocol APIRequestParameterType: Encodable { } From 4e69483db08adbda839b8910ac93c1054f70188f Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 26 May 2022 12:19:09 +0700 Subject: [PATCH 22/45] Update for new Network layer: - FeeHistory - GetAccount - GetBlockNumber BlockNumber now stores in UInt. --- .../EthereumAddress/EthereumAddress.swift | 2 + .../Promise+Web3+Eth+FeeHistory.swift | 17 ++--- .../Promise+Web3+Eth+GetAccounts.swift | 15 +---- .../Promise+Web3+Eth+GetBlockNumber.swift | 15 ++--- Sources/web3swift/Web3/Web3+GasOracle.swift | 8 +-- .../web3swift/Web3/Web3+InfuraProviders.swift | 2 +- .../remoteTests/GasOracleTests.swift | 64 +++++++++++-------- 7 files changed, 59 insertions(+), 64 deletions(-) diff --git a/Sources/web3swift/EthereumAddress/EthereumAddress.swift b/Sources/web3swift/EthereumAddress/EthereumAddress.swift index 620599d47..1ad1c8013 100755 --- a/Sources/web3swift/EthereumAddress/EthereumAddress.swift +++ b/Sources/web3swift/EthereumAddress/EthereumAddress.swift @@ -125,3 +125,5 @@ extension EthereumAddress { } extension EthereumAddress: Hashable { } + +extension EthereumAddress: APIResultType { } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index 0a3b09ee7..7634d6df3 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -9,19 +9,14 @@ import Foundation import BigInt +extension Web3.Oracle.FeeHistory: APIResultType { } + extension web3.Eth { - func feeHistory(blockCount: BigUInt, block: String, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { - let parameters: [APIRequestParameterType] = [blockCount.hexString, block, percentiles] + func feeHistory(blockCount: UInt, block: BlockNumber, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { + let requestCall: APIRequest = .feeHistory(blockCount, block, percentiles) - let request = JSONRPCRequestFabric.prepareRequest(.feeHistory, parameters: parameters) - let response = try await web3.dispatch(request) + let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) - guard let value: Web3.Oracle.FeeHistory = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift index c5e4c9705..4bbb55c9c 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift @@ -7,25 +7,16 @@ import Foundation import BigInt - extension web3.Eth { public func ownedAccounts() async throws -> [EthereumAddress] { - guard self.web3.provider.attachedKeystoreManager == nil else { return try self.web3.wallet.getAccounts() } + let requestCall: APIRequest = .getAccounts - let request = JSONRPCRequestFabric.prepareRequest(.getAccounts, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: [EthereumAddress] = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + let response: APIResponse<[EthereumAddress]> = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift index da6e82518..bd97ab27f 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift @@ -9,18 +9,11 @@ import BigInt extension web3.Eth { - public func blockNumber() async throws -> BigUInt { - let request = JSONRPCRequestFabric.prepareRequest(.blockNumber, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: BigUInt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + public func blockNumber() async throws -> UInt { + let requestCall: APIRequest = .blockNumber + let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index 4bb4dbd24..b7b23f2c2 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -25,7 +25,7 @@ extension Web3 { var block: BlockNumber /// Count of blocks to include in dataset - var blockCount: BigUInt + var blockCount: UInt /// Percentiles /// @@ -48,7 +48,7 @@ extension Web3 { /// - block: Number of block from which counts starts backward /// - blockCount: Count of block to calculate statistics /// - percentiles: Percentiles of fees to which result of predictions will be split in - public init(_ provider: web3, block: BlockNumber = .latest, blockCount: BigUInt = 20, percentiles: [Double] = [25, 50, 75]) { + public init(_ provider: web3, block: BlockNumber = .latest, blockCount: UInt = 20, percentiles: [Double] = [25, 50, 75]) { self.web3Provider = provider self.block = block self.blockCount = blockCount @@ -89,7 +89,7 @@ extension Web3 { // TODO: Disabled until 3.0 version, coz `distance` available from iOS 13. // guard feeHistory == nil, forceDropCache, feeHistory!.timestamp.distance(to: Date()) > cacheTimeout else { return feeHistory! } - return try await eth.feeHistory(blockCount: blockCount, block: block.stringValue, percentiles: percentiles) + return try await eth.feeHistory(blockCount: blockCount, block: block, percentiles: percentiles) } /// Suggesting tip values @@ -122,7 +122,7 @@ extension Web3 { } private func suggestGasFeeLegacy() async throws -> [BigUInt] { - var latestBlockNumber: BigUInt = 0 + var latestBlockNumber: UInt = 0 switch block { case .latest: latestBlockNumber = try await eth.getBlockNumber() case let .exact(number): latestBlockNumber = number diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index d1ad0af79..29494ced0 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -14,7 +14,7 @@ public enum BlockNumber { /// Earliest block of a chain case earliest /// Exact block number - case exact(BigUInt) + case exact(UInt) /// Block number as a hex string public var stringValue: String { diff --git a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift index 63fab36a6..7419d121d 100644 --- a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift +++ b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift @@ -13,7 +13,7 @@ import BigInt // MARK: Works only with network connection class OracleTests: XCTestCase { - let blockNumber: BigUInt = 14571792 + let blockNumber: UInt = 14571792 func testPretictBaseFee() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) @@ -66,30 +66,44 @@ class OracleTests: XCTestCase { XCTAssertEqual(bothFeesPercentiles?.tip, etalonPercentiles.1, "Arrays should be equal") } - func testPredictLegacyGasPrice() async throws { - let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) - let etalonPercentiles: [BigUInt] = [ - 93253857566, // 10 percentile - 106634912620, // 40 percentile - 111000000000, // 60 percentile - 127210686305 // 90 percentile - ] - - let gasPriceLegacyPercentiles = await oracle.gasPriceLegacyPercentiles() - XCTAssertEqual(gasPriceLegacyPercentiles, etalonPercentiles, "Arrays should be equal") - } - - func testAllTransactionInBlockDecodesWell() async throws { - let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) - let blockWithTransaction = try await web3.eth.getBlockByNumber(blockNumber, fullTransactions: true) +// func testPredictLegacyGasPrice() async throws { +// let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) +// lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) +// let etalonPercentiles: [BigUInt] = [ +// 93253857566, // 10 percentile +// 106634912620, // 40 percentile +// 111000000000, // 60 percentile +// 127210686305 // 90 percentile +// ] +// +// let gasPriceLegacyPercentiles = await oracle.gasPriceLegacyPercentiles() +// XCTAssertEqual(gasPriceLegacyPercentiles, etalonPercentiles, "Arrays should be equal") +// } +// +// func testAllTransactionInBlockDecodesWell() async throws { +// let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) +// lazy var oracle: Web3.Oracle = .init(web3, block: .exact(blockNumber), blockCount: 20, percentiles: [10, 40, 60, 90]) +// let blockWithTransaction = try await web3.eth.getBlockByNumber(blockNumber, fullTransactions: true) +// +// let nullTransactions = blockWithTransaction.transactions.filter { +// guard case .null = $0 else { return false } +// return true +// } +// +// XCTAssert(nullTransactions.isEmpty, "This amount transaction fails to decode: \(nullTransactions.count)") +// } - let nullTransactions = blockWithTransaction.transactions.filter { - guard case .null = $0 else { return false } - return true - } - XCTAssert(nullTransactions.isEmpty, "This amount transaction fails to decode: \(nullTransactions.count)") - } + // FIXME: Move it to external test suit. +// func testBlockNumber() async throws { +// let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) +// let latestBlockNumber = try await web3.eth.getBlockNumber() +// print(latestBlockNumber) +// } +// +// func testgetAccounts() async throws { +// let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) +// let accounts = try await web3.eth.getAccounts() +// print(accounts) +// } } From 635009a006ed661bf3a4ea623ee66c81a857cc7d Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 17:07:19 +0700 Subject: [PATCH 23/45] Update for network layer: - `GetAccoung` - `GetBalance` - `GetBlockByHash` - `GetBlockByNumber` --- Sources/web3swift/API/Web3+APIMethod.swift | 28 +++++++++++++++++-- .../Promise+Web3+Eth+FeeHistory.swift | 2 -- .../Promise+Web3+Eth+GetAccounts.swift | 6 +--- .../Promise+Web3+Eth+GetBalance.swift | 20 ++++--------- .../Promise+Web3+Eth+GetBlockByHash.swift | 20 ++++--------- .../Promise+Web3+Eth+GetBlockByNumber.swift | 27 +++++------------- 6 files changed, 45 insertions(+), 58 deletions(-) diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift index f5bb826ed..d6d94f8ed 100644 --- a/Sources/web3swift/API/Web3+APIMethod.swift +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -44,7 +44,7 @@ public enum APIRequest { case getCode(Address, BlockNumber) case getBlockByHash(Hash, Bool) - case getBlockByNumber(Hash, Bool) + case getBlockByNumber(BlockNumber, Bool) /// Returns fee history with a respect to given setup /// @@ -99,6 +99,9 @@ extension APIRequest { switch self { case .blockNumber: return UInt.self case .getAccounts: return [EthereumAddress].self + case .getBalance: return BigUInt.self + case .getBlockByHash: return Block.self + case .getBlockByNumber: return Block.self case .feeHistory: return Web3.Oracle.FeeHistory.self default: return String.self } @@ -115,43 +118,62 @@ extension APIRequest { switch self { case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: return [RequestParameter]() + case let .sendRawTransaction(hash): return [RequestParameter.string(hash)] + case .sendTransaction(let transactionParameters): return [RequestParameter.transaction(transactionParameters)] + case .getTransactionByHash(let hash): return [RequestParameter.string(hash)] + case .getTransactionReceipt(let receipt): return [RequestParameter.string(receipt)] + case .getLogs(let eventFilterParameters): return [RequestParameter.eventFilter(eventFilterParameters)] + case .personalSign(let address, let data): // FIXME: Add second parameter return [RequestParameter.string(address)] + case .call(let transactionParameters): return [RequestParameter.transaction(transactionParameters)] + case .getTransactionCount(let address, let blockNumber): return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getBalance(let address, let blockNumber): return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getStorageAt(let address, let hash, let blockNumber): return [RequestParameter.string(address), RequestParameter.string(hash), RequestParameter.string(blockNumber.stringValue)] + case .getCode(let address, let blockNumber): return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] + case .getBlockByHash(let hash, let bool): return [RequestParameter.string(hash), RequestParameter.bool(bool)] - case .getBlockByNumber(let hash, let bool): - return [RequestParameter.string(hash), RequestParameter.bool(bool)] + + case .getBlockByNumber(let block, let bool): + return [RequestParameter.string(block.stringValue), RequestParameter.bool(bool)] + case .feeHistory(let uInt, let blockNumber, let array): return [RequestParameter.string(uInt.hexString), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] + case .createAccount(let string): return [RequestParameter]() + case .unlockAccount(let address, let string, let optional): return [RequestParameter]() + case .getTxPoolStatus: return [RequestParameter]() + case .getTxPoolContent: return [RequestParameter]() + case .getTxPoolInspect: return [RequestParameter]() } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index 7634d6df3..bd3c74d7f 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -14,9 +14,7 @@ extension Web3.Oracle.FeeHistory: APIResultType { } extension web3.Eth { func feeHistory(blockCount: UInt, block: BlockNumber, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { let requestCall: APIRequest = .feeHistory(blockCount, block, percentiles) - let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) - return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift index 4bbb55c9c..8b8bbd7c0 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift @@ -12,11 +12,7 @@ extension web3.Eth { guard self.web3.provider.attachedKeystoreManager == nil else { return try self.web3.wallet.getAccounts() } - - let requestCall: APIRequest = .getAccounts - - let response: APIResponse<[EthereumAddress]> = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) - + let response: APIResponse<[EthereumAddress]> = try await APIRequest.sendRequest(with: web3.provider, for: .getAccounts) return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift index 0aaa11f9e..05aa2e49e 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift @@ -9,21 +9,13 @@ import Foundation import BigInt extension web3.Eth { - public func getBalance(for address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { - let addr = address.address - return try await getBalance(address: addr, onBlock: onBlock) + public func getBalance(for address: EthereumAddress, onBlock: BlockNumber = .latest) async throws -> BigUInt { + try await getBalance(for: address.address, onBlock: onBlock) } - public func getBalance(address: String, onBlock: String = "latest") async throws -> BigUInt { - let request = JSONRPCRequestFabric.prepareRequest(.getBalance, parameters: [address.lowercased(), onBlock]) - let response = try await web3.dispatch(request) - - guard let value: BigUInt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + public func getBalance(for address: Address, onBlock: BlockNumber = .latest) async throws -> BigUInt { + let requestCall: APIRequest = .getBalance(address, onBlock) + let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift index cf4eb8a5c..7ee55e72a 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift @@ -9,22 +9,14 @@ import BigInt extension web3.Eth { - public func block(for hash: Data, fullTransactions: Bool = false) async throws -> Block { + public func block(by hash: Data, fullTransactions: Bool = false) async throws -> Block { let hashString = hash.toHexString().addHexPrefix() - return try await block(for: hashString, fullTransactions: fullTransactions) + return try await block(by: hashString, fullTransactions: fullTransactions) } - public func block(for hash: String, fullTransactions: Bool = false) async throws -> Block { - let request = JSONRPCRequestFabric.prepareRequest(.getBlockByHash, parameters: [hash, fullTransactions]) - let response = try await web3.dispatch(request) - - guard let value: Block = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + public func block(by hash: String, fullTransactions: Bool = false) async throws -> Block { + let requestCall: APIRequest = .getBlockByHash(hash, fullTransactions) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift index eeaf9bb93..80dcfd27f 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift @@ -9,27 +9,14 @@ import BigInt extension web3.Eth { - public func blockBy(number: UInt, fullTransactions: Bool = false) async throws -> Block { - let block = String(number, radix: 16).addHexPrefix() - return try await blockBy(number: block, fullTransactions: fullTransactions) + public func block(by number: UInt, fullTransactions: Bool = false) async throws -> Block { + let blockNumber = BlockNumber.exact(number) + return try await block(by: blockNumber, fullTransactions: fullTransactions) } - public func blockBy(number: BigUInt, fullTransactions: Bool = false) async throws -> Block { - let block = String(number, radix: 16).addHexPrefix() - return try await blockBy(number: block, fullTransactions: fullTransactions) - } - - public func blockBy(number: String, fullTransactions: Bool = false) async throws -> Block { - let request = JSONRPCRequestFabric.prepareRequest(.getBlockByNumber, parameters: [number, fullTransactions]) - let response = try await web3.dispatch(request) - - guard let value: Block = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + public func block(by number: BlockNumber, fullTransactions: Bool = false) async throws -> Block { + let requestCall: APIRequest = .getBlockByNumber(number, fullTransactions) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } From 27a28e2eb72c396ac4bacd067945651bc0a736dc Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 17:08:21 +0700 Subject: [PATCH 24/45] Update clients code for changes made --- Sources/web3swift/Web3/Web3+EventParser.swift | 2 +- Sources/web3swift/Web3/Web3+GasOracle.swift | 6 ++---- Sources/web3swift/Web3/Web3+Structures.swift | 2 ++ .../localTests/web3swiftBasicLocalNodeTests.swift | 8 ++++---- .../localTests/web3swiftPromisesTests.swift | 2 +- Tests/web3swiftTests/localTests/web3swiftUserCases.swift | 2 +- Tests/web3swiftTests/remoteTests/InfuraTests.swift | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+EventParser.swift b/Sources/web3swift/Web3/Web3+EventParser.swift index 8587b801f..2eb5e57f8 100755 --- a/Sources/web3swift/Web3/Web3+EventParser.swift +++ b/Sources/web3swift/Web3/Web3+EventParser.swift @@ -118,7 +118,7 @@ extension web3.web3contract.EventParser { throw Web3Error.inputError(desc: "Can not mix parsing specific block and using block range filter") } - let res = try await self.web3.eth.blockBy(number: blockNumber) + let res = try await self.web3.eth.block(by: blockNumber) return try await self.parseBlockPromise(res) } diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index b7b23f2c2..b51f2e231 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -138,15 +138,13 @@ extension Web3 { // TODO: Make me work with cache let blocks = try await withThrowingTaskGroup(of: Block.self, returning: [Block].self) { group in - (latestBlockNumber - blockCount ... latestBlockNumber) - .forEach { transaction in + .forEach { block in group.addTask { - try await self.eth.getBlockByNumber(transaction, fullTransactions: true) + try await self.eth.block(by: .exact(block), fullTransactions: true) } } - var collected = [Block]() for try await value in group { diff --git a/Sources/web3swift/Web3/Web3+Structures.swift b/Sources/web3swift/Web3/Web3+Structures.swift index 14aafa5e6..9792a768d 100755 --- a/Sources/web3swift/Web3/Web3+Structures.swift +++ b/Sources/web3swift/Web3/Web3+Structures.swift @@ -291,6 +291,8 @@ extension Block { } } +extension Block: APIResultType { } + public struct EventParserResult: EventParserResultProtocol { public var eventName: String public var transactionReceipt: TransactionReceipt? diff --git a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift index ad2e14fc2..ef1df2248 100755 --- a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift @@ -61,8 +61,8 @@ class web3swiftBasicLocalNodeTests: XCTestCase { sendTx.transactionOptions.value = valueToSend sendTx.transactionOptions.from = allAddresses[0] - let balanceBeforeTo = try await web3.eth.getBalance(address: sendToAddress) - let balanceBeforeFrom = try await web3.eth.getBalance(address: allAddresses[0]) + let balanceBeforeTo = try await web3.eth.getBalance(for: sendToAddress) + let balanceBeforeFrom = try await web3.eth.getBalance(for: allAddresses[0]) print("Balance before to: " + balanceBeforeTo.description) print("Balance before from: " + balanceBeforeFrom.description) @@ -86,8 +86,8 @@ class web3swiftBasicLocalNodeTests: XCTestCase { print(details) - let balanceAfterTo = try await web3.eth.getBalance(address: sendToAddress) - let balanceAfterFrom = try await web3.eth.getBalance(address: allAddresses[0]) + let balanceAfterTo = try await web3.eth.getBalance(for: sendToAddress) + let balanceAfterFrom = try await web3.eth.getBalance(for: allAddresses[0]) print("Balance after to: " + balanceAfterTo.description) print("Balance after from: " + balanceAfterFrom.description) diff --git a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift index ea58ff663..92430efc9 100755 --- a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift @@ -18,7 +18,7 @@ class web3swiftPromisesTests: XCTestCase { func testGetBalancePromise() async throws { let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let balance = try await web3.eth.getBalance(address: "0xe22b8979739D724343bd002F9f432F5990879901") + let balance = try await web3.eth.getBalance(for: "0xe22b8979739D724343bd002F9f432F5990879901") print(balance) } diff --git a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift index 3acfe6cd8..a3728cb6b 100755 --- a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift +++ b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift @@ -106,7 +106,7 @@ class web3swiftUserCases: XCTestCase { func testNonBatchedRequest() async throws { let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) let address = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - let balanceResult = try await web3.eth.getBalance(address: address) + let balanceResult = try await web3.eth.getBalance(for: address) print(balanceResult) } } diff --git a/Tests/web3swiftTests/remoteTests/InfuraTests.swift b/Tests/web3swiftTests/remoteTests/InfuraTests.swift index 2d4852ffe..dae46a96b 100755 --- a/Tests/web3swiftTests/remoteTests/InfuraTests.swift +++ b/Tests/web3swiftTests/remoteTests/InfuraTests.swift @@ -15,7 +15,7 @@ class InfuraTests: XCTestCase { do { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) let address = EthereumAddress("0xd61b5ca425F8C8775882d4defefC68A6979DBbce")! - let balance = try await web3.eth.getBalance(address: address) + let balance = try await web3.eth.getBalance(for: address) let balString = Web3.Utils.formatToEthereumUnits(balance, toUnits: .eth, decimals: 3) print(balString!) } catch { @@ -32,13 +32,13 @@ class InfuraTests: XCTestCase { func testGetBlockByNumber1() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByNumber("latest", fullTransactions: false) + let result = try await web3.eth.getBlockByNumber(.latest, fullTransactions: false) print(result) } func testGetBlockByNumber2() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByNumber(UInt(5184323), fullTransactions: true) + let result = try await web3.eth.getBlockByNumber(.exact(5184323), fullTransactions: true) print(result) let transactions = result.transactions for transaction in transactions { @@ -54,7 +54,7 @@ class InfuraTests: XCTestCase { func testGetBlockByNumber3() async throws { do { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let _ = try await web3.eth.getBlockByNumber(UInt(1000000000), fullTransactions: true) + let _ = try await web3.eth.getBlockByNumber(.exact(1000000000), fullTransactions: true) XCTFail() } catch { From 351b671c6f214bcdc4e1dbb837638ac02b5038f0 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 17:19:35 +0700 Subject: [PATCH 25/45] Update for network layer: - `GasPrice` - `GetTransactionCount` --- Sources/web3swift/API/Web3+APIMethod.swift | 2 ++ .../Promise+Web3+Eth+GetGasPrice.swift | 13 ++---------- ...Promise+Web3+Eth+GetTransactionCount.swift | 21 ++++++------------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift index d6d94f8ed..08524b16c 100644 --- a/Sources/web3swift/API/Web3+APIMethod.swift +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -102,7 +102,9 @@ extension APIRequest { case .getBalance: return BigUInt.self case .getBlockByHash: return Block.self case .getBlockByNumber: return Block.self + case .gasPrice: return BigUInt.self case .feeHistory: return Web3.Oracle.FeeHistory.self + case .getTransactionCount: return UInt.self default: return String.self } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift index 9b4120e4d..afa45f950 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift @@ -10,16 +10,7 @@ import BigInt extension web3.Eth { public func gasPrice() async throws -> BigUInt { - let request = JSONRPCRequestFabric.prepareRequest(.gasPrice, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: BigUInt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: .gasPrice) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift index af1391834..479e24554 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift @@ -5,25 +5,16 @@ // import Foundation -import BigInt extension web3.Eth { - public func getTransactionCount(for address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { - let addr = address.address - return try await getTransactionCount(address: addr, onBlock: onBlock) + public func getTransactionCount(for address: EthereumAddress, onBlock: BlockNumber) async throws -> UInt { + try await getTransactionCount(address: address.address, onBlock: onBlock) } - public func getTransactionCount(address: String, onBlock: String = "latest") async throws -> BigUInt { - let request = JSONRPCRequestFabric.prepareRequest(.getTransactionCount, parameters: [address.lowercased(), onBlock]) - let response = try await web3.dispatch(request) - - guard let value: BigUInt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + public func getTransactionCount(address: Address, onBlock: BlockNumber) async throws -> UInt { + let requestCall: APIRequest = .getTransactionCount(address, onBlock) + let response: APIResponse = APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } From 7c5126a0e68f9802c394772114391756c6c21993 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 17:34:17 +0700 Subject: [PATCH 26/45] Refactor code a bit. --- .../web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift | 3 +-- .../Promises/Promise+Web3+Eth+GetBlockByNumber.swift | 3 +-- .../web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift | 5 +---- Sources/web3swift/Transaction/EthereumTransaction.swift | 3 +++ 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift index 7ee55e72a..fb0c32d31 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift @@ -10,8 +10,7 @@ import BigInt extension web3.Eth { public func block(by hash: Data, fullTransactions: Bool = false) async throws -> Block { - let hashString = hash.toHexString().addHexPrefix() - return try await block(by: hashString, fullTransactions: fullTransactions) + try await block(by: hashString.toHexString().addHexPrefix(), fullTransactions: fullTransactions) } public func block(by hash: String, fullTransactions: Bool = false) async throws -> Block { diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift index 80dcfd27f..80bd037f3 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift @@ -10,8 +10,7 @@ import BigInt extension web3.Eth { public func block(by number: UInt, fullTransactions: Bool = false) async throws -> Block { - let blockNumber = BlockNumber.exact(number) - return try await block(by: blockNumber, fullTransactions: fullTransactions) + try await block(by: BlockNumber.exact(number), fullTransactions: fullTransactions) } public func block(by number: BlockNumber, fullTransactions: Bool = false) async throws -> Block { diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift index bd97ab27f..f31a161d2 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift @@ -10,10 +10,7 @@ import BigInt extension web3.Eth { public func blockNumber() async throws -> UInt { - let requestCall: APIRequest = .blockNumber - - let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) - + let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: .blockNumber) return response.result } } diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/web3swift/Transaction/EthereumTransaction.swift index e6f3b0cdc..700aeb302 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/web3swift/Transaction/EthereumTransaction.swift @@ -177,6 +177,8 @@ public struct EthereumTransaction: CustomStringConvertible { /// - Returns: a TransactionParameters object suitable for passing to Web3+JSONRPC provider public func encodeAsDictionary(from: EthereumAddress? = nil) -> TransactionParameters? { self.envelope.encodeAsDictionary(from: from) } + + // FIXME: Move this logic into place where it supposed to be. /// create a JSON RPC Request object for the given transacton /// - Parameters: /// - method: RPC request method @@ -207,6 +209,7 @@ public struct EthereumTransaction: CustomStringConvertible { return self.envelope.encode(for: type) } + // FIXME: Move this logic into place where it supposed to be. /// creates a Raw RPC request transaction for the given Transaction /// - Parameter transaction: EthereumTransaction to encode /// - Returns: a JSONRPCrequest object From 412972bcce78a372247d541d095e2069ecff2ff8 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 18:17:55 +0700 Subject: [PATCH 27/45] Update for network layer: - `GetCode` - `GetTransactionCount` - `GetTransactionReceipt` - `CreateAccount` - `UnlockAccount` --- .../web3swift/API/HexDecodableProtocols.swift | 2 ++ Sources/web3swift/API/Web3+APIMethod.swift | 8 ++++++- .../Promise+Web3+Eth+GetBlockByHash.swift | 2 +- .../Promises/Promise+Web3+Eth+GetCode.swift | 22 ++++++------------ ...Promise+Web3+Eth+GetTransactionCount.swift | 2 +- ...omise+Web3+Eth+GetTransactionReceipt.swift | 20 +++++----------- .../Promise+Web3+Personal+CreateAccount.swift | 15 +++--------- .../Promise+Web3+Personal+UnlockAccount.swift | 23 ++++--------------- 8 files changed, 32 insertions(+), 62 deletions(-) diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/web3swift/API/HexDecodableProtocols.swift index 1262a247e..b1a388f69 100644 --- a/Sources/web3swift/API/HexDecodableProtocols.swift +++ b/Sources/web3swift/API/HexDecodableProtocols.swift @@ -13,6 +13,8 @@ extension Array: APIResultType where Element: APIResultType { } extension String: APIResultType { } +extension Bool: APIResultType { } + /// This is utility protocol for decoding API Responses /// /// You better not use it in any other part of a bit of code except `APIResponse` decoding. diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift index 08524b16c..0c9be1250 100644 --- a/Sources/web3swift/API/Web3+APIMethod.swift +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -27,7 +27,7 @@ public enum APIRequest { case sendRawTransaction(Hash) case sendTransaction(TransactionParameters) case getTransactionByHash(Hash) - case getTransactionReceipt(Receipt) + case getTransactionReceipt(Hash) case getLogs(EventFilterParameters) case personalSign(Address, Data) case call(TransactionParameters) @@ -105,6 +105,10 @@ extension APIRequest { case .gasPrice: return BigUInt.self case .feeHistory: return Web3.Oracle.FeeHistory.self case .getTransactionCount: return UInt.self + case .getCode: return Hash.self + case .getTransactionReceipt: return TransactionReceipt.self + case .createAccount: return EthereumAddress.self + case .unlockAccount: return Bool.self default: return String.self } } @@ -225,6 +229,8 @@ extension APIRequest { guard let httpResponse = response as? HTTPURLResponse, 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } + /// This bit of code is purposed to work with literal types that comes in Response in hexString type. + /// Currently it's just any kind of Integers like `(U)Int`, `Big(U)Int`. if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { /// This types for sure conformed with `LiteralInitiableFromString` // FIXME: Make appropriate error diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift index fb0c32d31..20f2dd2e6 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift @@ -10,7 +10,7 @@ import BigInt extension web3.Eth { public func block(by hash: Data, fullTransactions: Bool = false) async throws -> Block { - try await block(by: hashString.toHexString().addHexPrefix(), fullTransactions: fullTransactions) + try await block(by: hash.toHexString().addHexPrefix(), fullTransactions: fullTransactions) } public func block(by hash: String, fullTransactions: Bool = false) async throws -> Block { diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift index b29e51f41..f90c574ba 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift @@ -10,21 +10,13 @@ import Foundation import BigInt extension web3.Eth { - public func code(for address: EthereumAddress, onBlock: String = "latest") async throws -> String { - let addr = address.address - return try await code(for : addr, onBlock: onBlock) + public func code(for address: EthereumAddress, onBlock: BlockNumber) async throws -> Hash { + try await code(for : address.address, onBlock: onBlock) } - public func code(for address: String, onBlock: String = "latest") async throws -> String { - let request = JSONRPCRequestFabric.prepareRequest(.getCode, parameters: [address.lowercased(), onBlock]) - let response = try await web3.dispatch(request) - - guard let value: String = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + + public func code(for address: Address, onBlock: BlockNumber) async throws -> Hash { + let requestCall: APIRequest = .getCode(address, onBlock) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift index 479e24554..4e2797c06 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift @@ -14,7 +14,7 @@ extension web3.Eth { public func getTransactionCount(address: Address, onBlock: BlockNumber) async throws -> UInt { let requestCall: APIRequest = .getTransactionCount(address, onBlock) - let response: APIResponse = APIRequest.sendRequest(with: self.provider, for: requestCall) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift index 72cea5d9c..e15a88649 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift @@ -7,24 +7,16 @@ import Foundation import BigInt +extension TransactionReceipt: APIResultType { } extension web3.Eth { public func transactionReceipt(_ txhash: Data) async throws -> TransactionReceipt { - let hashString = txhash.toHexString().addHexPrefix() - return try await self.transactionReceipt(hashString) + try await self.transactionReceipt(txhash.toHexString().addHexPrefix()) } - public func transactionReceipt(_ txhash: String) async throws -> TransactionReceipt { - let request = JSONRPCRequestFabric.prepareRequest(.getTransactionReceipt, parameters: [txhash]) - let response = try await web3.dispatch(request) - - guard let value: TransactionReceipt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + public func transactionReceipt(_ txhash: Hash) async throws -> TransactionReceipt { + let requestCall: APIRequest = .getTransactionReceipt(txhash) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift b/Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift index 74d41537d..ef89215ad 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift @@ -10,21 +10,12 @@ import BigInt extension web3.Personal { public func createAccount(password: String = "web3swift") async throws -> EthereumAddress { - guard self.web3.provider.attachedKeystoreManager == nil else { throw Web3Error.inputError(desc: "Creating account in a local keystore with this method is not supported") } - let request = JSONRPCRequestFabric.prepareRequest(.createAccount, parameters: [password]) - let response = try await self.web3.dispatch(request) - - guard let value: EthereumAddress = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + let requestCall: APIRequest = .createAccount(password) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift index a9027eba4..58bee98cb 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift @@ -10,29 +10,16 @@ import BigInt extension web3.Personal { public func unlock(account: EthereumAddress, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { - let addr = account.address - return try await unlock(account: addr, password: password, seconds: seconds) + try await unlock(account: account.address, password: password, seconds: seconds) } - public func unlock(account: String, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { - + public func unlock(account: Address, password: String = "web3swift", seconds: UInt = 300) async throws -> Bool { guard self.web3.provider.attachedKeystoreManager == nil else { throw Web3Error.inputError(desc: "Can not unlock a local keystore") } - let parameters: [APIRequestParameterType] = [account.lowercased(), password, seconds] - - let request = JSONRPCRequestFabric.prepareRequest(.unlockAccount, parameters: parameters) - - let response = try await self.web3.dispatch(request) - - guard let value: Bool = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - + let requestCall: APIRequest = .unlockAccount(account, password, seconds) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result } } From 2de0d21ff489764a1896f50584dd3e26b5df905d Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 20:41:03 +0700 Subject: [PATCH 28/45] Revert `BigUInt` to `UInt` type changes. This changes will follow that every math operation within Transaction either Block properties will require to cast type back and forth, so such pedantic behavior didn't worth it. --- Sources/web3swift/API/Web3+APIMethod.swift | 6 +++--- .../web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift | 2 +- .../Promises/Promise+Web3+Eth+GetBlockByNumber.swift | 2 +- .../Promises/Promise+Web3+Eth+GetBlockNumber.swift | 4 ++-- .../Promises/Promise+Web3+Eth+GetTransactionCount.swift | 7 ++++--- Sources/web3swift/Web3/Web3+EventParser.swift | 4 ++-- Sources/web3swift/Web3/Web3+GasOracle.swift | 6 +++--- Sources/web3swift/Web3/Web3+Protocols.swift | 4 ++-- Tests/web3swiftTests/remoteTests/GasOracleTests.swift | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/Web3+APIMethod.swift index 0c9be1250..09a2d62d7 100644 --- a/Sources/web3swift/API/Web3+APIMethod.swift +++ b/Sources/web3swift/API/Web3+APIMethod.swift @@ -58,7 +58,7 @@ public enum APIRequest { /// - [Double]: A monotonically increasing list of percentile values. /// For each block in the requested range, the transactions will be sorted in ascending order /// by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed." - case feeHistory(UInt, BlockNumber, [Double]) + case feeHistory(BigUInt, BlockNumber, [Double]) // MARK: - Additional API /// Creates new account. @@ -97,14 +97,14 @@ extension APIRequest { public var responseType: APIResultType.Type { switch self { - case .blockNumber: return UInt.self + case .blockNumber: return BigUInt.self case .getAccounts: return [EthereumAddress].self case .getBalance: return BigUInt.self case .getBlockByHash: return Block.self case .getBlockByNumber: return Block.self case .gasPrice: return BigUInt.self case .feeHistory: return Web3.Oracle.FeeHistory.self - case .getTransactionCount: return UInt.self + case .getTransactionCount: return BigUInt.self case .getCode: return Hash.self case .getTransactionReceipt: return TransactionReceipt.self case .createAccount: return EthereumAddress.self diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift index bd3c74d7f..a1c8e06b4 100644 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift @@ -12,7 +12,7 @@ import BigInt extension Web3.Oracle.FeeHistory: APIResultType { } extension web3.Eth { - func feeHistory(blockCount: UInt, block: BlockNumber, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { + func feeHistory(blockCount: BigUInt, block: BlockNumber, percentiles:[Double]) async throws -> Web3.Oracle.FeeHistory { let requestCall: APIRequest = .feeHistory(blockCount, block, percentiles) let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: requestCall) return response.result diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift index 80bd037f3..4d7feb07c 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift @@ -9,7 +9,7 @@ import BigInt extension web3.Eth { - public func block(by number: UInt, fullTransactions: Bool = false) async throws -> Block { + public func block(by number: BigUInt, fullTransactions: Bool = false) async throws -> Block { try await block(by: BlockNumber.exact(number), fullTransactions: fullTransactions) } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift index f31a161d2..1ab23a192 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift @@ -9,8 +9,8 @@ import BigInt extension web3.Eth { - public func blockNumber() async throws -> UInt { - let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: .blockNumber) + public func blockNumber() async throws -> BigUInt { + let response: APIResponse = try await APIRequest.sendRequest(with: web3.provider, for: .blockNumber) return response.result } } diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift index 4e2797c06..072bc0642 100755 --- a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift +++ b/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift @@ -5,16 +5,17 @@ // import Foundation +import BigInt extension web3.Eth { - public func getTransactionCount(for address: EthereumAddress, onBlock: BlockNumber) async throws -> UInt { + public func getTransactionCount(for address: EthereumAddress, onBlock: BlockNumber) async throws -> BigUInt { try await getTransactionCount(address: address.address, onBlock: onBlock) } - public func getTransactionCount(address: Address, onBlock: BlockNumber) async throws -> UInt { + public func getTransactionCount(address: Address, onBlock: BlockNumber) async throws -> BigUInt { let requestCall: APIRequest = .getTransactionCount(address, onBlock) - let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) return response.result } } diff --git a/Sources/web3swift/Web3/Web3+EventParser.swift b/Sources/web3swift/Web3/Web3+EventParser.swift index 2eb5e57f8..5a47fb2c8 100755 --- a/Sources/web3swift/Web3/Web3+EventParser.swift +++ b/Sources/web3swift/Web3/Web3+EventParser.swift @@ -36,7 +36,7 @@ extension web3.web3contract { - important: This call is synchronous */ - public func parseBlockByNumber(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] { + public func parseBlockByNumber(_ blockNumber: BigUInt) async throws -> [EventParserResultProtocol] { let result = try await self.parseBlockByNumberPromise(blockNumber) return result } @@ -112,7 +112,7 @@ extension web3.web3contract.EventParser { } - public func parseBlockByNumberPromise(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] { + public func parseBlockByNumberPromise(_ blockNumber: BigUInt) async throws -> [EventParserResultProtocol] { guard filter == nil || filter?.fromBlock == nil && filter?.toBlock == nil else { throw Web3Error.inputError(desc: "Can not mix parsing specific block and using block range filter") diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index b51f2e231..31cf17ff1 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -25,7 +25,7 @@ extension Web3 { var block: BlockNumber /// Count of blocks to include in dataset - var blockCount: UInt + var blockCount: BigUInt /// Percentiles /// @@ -48,7 +48,7 @@ extension Web3 { /// - block: Number of block from which counts starts backward /// - blockCount: Count of block to calculate statistics /// - percentiles: Percentiles of fees to which result of predictions will be split in - public init(_ provider: web3, block: BlockNumber = .latest, blockCount: UInt = 20, percentiles: [Double] = [25, 50, 75]) { + public init(_ provider: web3, block: BlockNumber = .latest, blockCount: BigUInt = 20, percentiles: [Double] = [25, 50, 75]) { self.web3Provider = provider self.block = block self.blockCount = blockCount @@ -122,7 +122,7 @@ extension Web3 { } private func suggestGasFeeLegacy() async throws -> [BigUInt] { - var latestBlockNumber: UInt = 0 + var latestBlockNumber: BigUInt = 0 switch block { case .latest: latestBlockNumber = try await eth.getBlockNumber() case let .exact(number): latestBlockNumber = number diff --git a/Sources/web3swift/Web3/Web3+Protocols.swift b/Sources/web3swift/Web3/Web3+Protocols.swift index ae264fc34..017e8843e 100755 --- a/Sources/web3swift/Web3/Web3+Protocols.swift +++ b/Sources/web3swift/Web3/Web3+Protocols.swift @@ -21,10 +21,10 @@ public protocol EventParserProtocol { func parseTransaction(_ transaction: EthereumTransaction) async throws -> [EventParserResultProtocol] func parseTransactionByHash(_ hash: Data) async throws -> [EventParserResultProtocol] func parseBlock(_ block: Block) async throws -> [EventParserResultProtocol] - func parseBlockByNumber(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] + func parseBlockByNumber(_ blockNumber: BigUInt) async throws -> [EventParserResultProtocol] func parseTransactionPromise(_ transaction: EthereumTransaction) async throws -> [EventParserResultProtocol] func parseTransactionByHashPromise(_ hash: Data) async throws -> [EventParserResultProtocol] - func parseBlockByNumberPromise(_ blockNumber: UInt) async throws -> [EventParserResultProtocol] + func parseBlockByNumberPromise(_ blockNumber: BigUInt) async throws -> [EventParserResultProtocol] func parseBlockPromise(_ block: Block) async throws -> [EventParserResultProtocol] } diff --git a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift index 7419d121d..105c19562 100644 --- a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift +++ b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift @@ -13,7 +13,7 @@ import BigInt // MARK: Works only with network connection class OracleTests: XCTestCase { - let blockNumber: UInt = 14571792 + let blockNumber: BigUInt = 14571792 func testPretictBaseFee() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) From 820772709a008a94c866a7ee60a2b2f2d4d9fed7 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 27 May 2022 20:53:23 +0700 Subject: [PATCH 29/45] Rename API calls files and folder --- Sources/web3swift/API/{Web3+APIMethod.swift => APIMethod.swift} | 0 .../{Web3+APIRequestParameter.swift => APIRequestParameter.swift} | 0 .../Eth+FeeHistory.swift} | 0 .../Eth+GetAccounts.swift} | 0 .../Eth+GetBalance.swift} | 0 .../Eth+GetBlockByHash.swift} | 0 .../Eth+GetBlockByNumber.swift} | 0 .../Eth+GetBlockNumber.swift} | 0 .../Eth+GetCode.swift} | 0 .../Eth+GetGasPrice.swift} | 0 .../Eth+GetTransactionCount.swift} | 0 .../Eth+GetTransactionReceipt.swift} | 0 .../Personal+CreateAccount.swift} | 0 .../Personal+UnlockAccount.swift} | 0 .../{Promises => EthereumAPICalls}/Promise+Web3+Eth+Call.swift | 0 .../Promise+Web3+Eth+EstimateGas.swift | 0 .../Promise+Web3+Eth+GetTransactionDetails.swift | 0 .../Promise+Web3+Eth+SendRawTransaction.swift | 0 .../Promise+Web3+Eth+SendTransaction.swift | 0 .../Promise+Web3+Personal+Sign.swift | 0 .../{Promises => EthereumAPICalls}/Promise+Web3+TxPool.swift | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename Sources/web3swift/API/{Web3+APIMethod.swift => APIMethod.swift} (100%) rename Sources/web3swift/API/{Web3+APIRequestParameter.swift => APIRequestParameter.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+FeeHistory.swift => EthereumAPICalls/Eth+FeeHistory.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetAccounts.swift => EthereumAPICalls/Eth+GetAccounts.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetBalance.swift => EthereumAPICalls/Eth+GetBalance.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetBlockByHash.swift => EthereumAPICalls/Eth+GetBlockByHash.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetBlockByNumber.swift => EthereumAPICalls/Eth+GetBlockByNumber.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetBlockNumber.swift => EthereumAPICalls/Eth+GetBlockNumber.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetCode.swift => EthereumAPICalls/Eth+GetCode.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetGasPrice.swift => EthereumAPICalls/Eth+GetGasPrice.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetTransactionCount.swift => EthereumAPICalls/Eth+GetTransactionCount.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Eth+GetTransactionReceipt.swift => EthereumAPICalls/Eth+GetTransactionReceipt.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Personal+CreateAccount.swift => EthereumAPICalls/Personal+CreateAccount.swift} (100%) rename Sources/web3swift/{Promises/Promise+Web3+Personal+UnlockAccount.swift => EthereumAPICalls/Personal+UnlockAccount.swift} (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Eth+Call.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Eth+EstimateGas.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Eth+GetTransactionDetails.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Eth+SendRawTransaction.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Eth+SendTransaction.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+Personal+Sign.swift (100%) rename Sources/web3swift/{Promises => EthereumAPICalls}/Promise+Web3+TxPool.swift (100%) diff --git a/Sources/web3swift/API/Web3+APIMethod.swift b/Sources/web3swift/API/APIMethod.swift similarity index 100% rename from Sources/web3swift/API/Web3+APIMethod.swift rename to Sources/web3swift/API/APIMethod.swift diff --git a/Sources/web3swift/API/Web3+APIRequestParameter.swift b/Sources/web3swift/API/APIRequestParameter.swift similarity index 100% rename from Sources/web3swift/API/Web3+APIRequestParameter.swift rename to Sources/web3swift/API/APIRequestParameter.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift b/Sources/web3swift/EthereumAPICalls/Eth+FeeHistory.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+FeeHistory.swift rename to Sources/web3swift/EthereumAPICalls/Eth+FeeHistory.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetAccounts.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetAccounts.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetAccounts.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetBalance.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetBalance.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetBalance.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetBlockByHash.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByHash.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetBlockByHash.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetBlockByNumber.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockByNumber.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetBlockByNumber.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetBlockNumber.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetBlockNumber.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetBlockNumber.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetCode.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetCode.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetCode.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetGasPrice.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetGasPrice.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetGasPrice.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetTransactionCount.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionCount.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetTransactionCount.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift b/Sources/web3swift/EthereumAPICalls/Eth+GetTransactionReceipt.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionReceipt.swift rename to Sources/web3swift/EthereumAPICalls/Eth+GetTransactionReceipt.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal+CreateAccount.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Personal+CreateAccount.swift rename to Sources/web3swift/EthereumAPICalls/Personal+CreateAccount.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal+UnlockAccount.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Personal+UnlockAccount.swift rename to Sources/web3swift/EthereumAPICalls/Personal+UnlockAccount.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+Call.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+Call.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+EstimateGas.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+EstimateGas.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionDetails.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+GetTransactionDetails.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+SendRawTransaction.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendRawTransaction.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+SendRawTransaction.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendRawTransaction.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Eth+SendTransaction.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Eth+SendTransaction.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+Personal+Sign.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Personal+Sign.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+Personal+Sign.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+Personal+Sign.swift diff --git a/Sources/web3swift/Promises/Promise+Web3+TxPool.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift similarity index 100% rename from Sources/web3swift/Promises/Promise+Web3+TxPool.swift rename to Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift From 216686e5f66e694701ab3803798a1d310316ba3c Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 17:18:10 +0700 Subject: [PATCH 30/45] Encapsulate request methods into APIRequest enum. - Delete `EthereumTransaction.createRequest` - Delete `CallingBlockPolicy` enum which duplicating `BlockNumber` enum --- Sources/web3swift/API/APIMethod.swift | 51 +++++++++----- .../EthereumAPICalls/Ethereum/Eth+Call.swift | 20 ++++++ .../Ethereum/Eth+EstimateGas.swift | 36 ++++++++++ .../{ => Ethereum}/Eth+FeeHistory.swift | 0 .../{ => Ethereum}/Eth+GetAccounts.swift | 0 .../{ => Ethereum}/Eth+GetBalance.swift | 0 .../{ => Ethereum}/Eth+GetBlockByHash.swift | 0 .../{ => Ethereum}/Eth+GetBlockByNumber.swift | 0 .../{ => Ethereum}/Eth+GetBlockNumber.swift | 0 .../{ => Ethereum}/Eth+GetCode.swift | 0 .../{ => Ethereum}/Eth+GetGasPrice.swift | 0 .../Eth+GetTransactionCount.swift | 0 .../Ethereum/Eth+GetTransactionDetails.swift | 22 ++++++ .../Eth+GetTransactionReceipt.swift | 0 .../Eth+SendRawTransaction.swift} | 20 ++---- .../Ethereum/Eth+SendTransaction.swift | 61 ++++++++++++++++ .../Personal+CreateAccount.swift | 0 .../Personal+Sign.swift} | 16 ++--- .../Personal+UnlockAccount.swift | 0 .../Promise+Web3+Eth+Call.swift | 26 ------- .../Promise+Web3+Eth+EstimateGas.swift | 45 ------------ ...omise+Web3+Eth+GetTransactionDetails.swift | 30 -------- .../Promise+Web3+Eth+SendTransaction.swift | 69 ------------------- .../Transaction/EthereumTransaction.swift | 43 ------------ .../web3swift/Web3/Web3+InfuraProviders.swift | 10 +-- Sources/web3swift/Web3/Web3+Options.swift | 21 +----- 26 files changed, 190 insertions(+), 280 deletions(-) create mode 100755 Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift create mode 100755 Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+FeeHistory.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetAccounts.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetBalance.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetBlockByHash.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetBlockByNumber.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetBlockNumber.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetCode.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetGasPrice.swift (100%) rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetTransactionCount.swift (100%) create mode 100755 Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift rename Sources/web3swift/EthereumAPICalls/{ => Ethereum}/Eth+GetTransactionReceipt.swift (100%) rename Sources/web3swift/EthereumAPICalls/{Promise+Web3+Eth+SendRawTransaction.swift => Ethereum/Eth+SendRawTransaction.swift} (58%) create mode 100755 Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift rename Sources/web3swift/EthereumAPICalls/{ => Personal}/Personal+CreateAccount.swift (100%) rename Sources/web3swift/EthereumAPICalls/{Promise+Web3+Personal+Sign.swift => Personal/Personal+Sign.swift} (58%) rename Sources/web3swift/EthereumAPICalls/{ => Personal}/Personal+UnlockAccount.swift (100%) delete mode 100755 Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift delete mode 100755 Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift delete mode 100755 Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift delete mode 100755 Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 09a2d62d7..0cf4ad740 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -22,15 +22,14 @@ public enum APIRequest { case getNetwork case getAccounts // ?? - case estimateGas - + case estimateGas(TransactionParameters, BlockNumber) case sendRawTransaction(Hash) - case sendTransaction(TransactionParameters) + case sendTransaction(TransactionParameters, BlockNumber) case getTransactionByHash(Hash) case getTransactionReceipt(Hash) case getLogs(EventFilterParameters) - case personalSign(Address, Data) - case call(TransactionParameters) + case personalSign(Address, String) + case call(TransactionParameters, BlockNumber) case getTransactionCount(Address, BlockNumber) case getBalance(Address, BlockNumber) @@ -88,6 +87,9 @@ public enum APIRequest { case getTxPoolInspect // No in Eth API } +// FIXME: This conformance should be changed to `LiteralInitiableFromString` +extension Data: APIResultType { } + extension APIRequest { public var method: REST { switch self { @@ -109,7 +111,21 @@ extension APIRequest { case .getTransactionReceipt: return TransactionReceipt.self case .createAccount: return EthereumAddress.self case .unlockAccount: return Bool.self - default: return String.self + case .getTransactionByHash: return TransactionDetails.self + case .sendTransaction: return Hash.self + case .sendRawTransaction: return Hash.self + case .estimateGas: return BigUInt.self + case .call: return Data.self + // FIXME: Not checked + case .getNetwork: return UInt.self + case .personalSign: return Data.self + + // FIXME: Not implemented + case .getLogs: return String.self + case .getStorageAt: return String.self + case .getTxPoolStatus: return String.self + case .getTxPoolContent: return String.self + case .getTxPoolInspect: return String.self } } @@ -122,14 +138,17 @@ extension APIRequest { var parameters: [RequestParameter] { switch self { - case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .estimateGas: + case .gasPrice, .blockNumber, .getNetwork, .getAccounts: return [RequestParameter]() + case .estimateGas(let transactionParameters, let blockNumber): + return [RequestParameter.transaction(transactionParameters), RequestParameter.string(blockNumber.stringValue)] + case let .sendRawTransaction(hash): return [RequestParameter.string(hash)] - case .sendTransaction(let transactionParameters): - return [RequestParameter.transaction(transactionParameters)] + case .sendTransaction(let transactionParameters, let blockNumber): + return [RequestParameter.transaction(transactionParameters), RequestParameter.string(blockNumber.stringValue)] case .getTransactionByHash(let hash): return [RequestParameter.string(hash)] @@ -140,12 +159,12 @@ extension APIRequest { case .getLogs(let eventFilterParameters): return [RequestParameter.eventFilter(eventFilterParameters)] - case .personalSign(let address, let data): + case .personalSign(let address, let string): // FIXME: Add second parameter - return [RequestParameter.string(address)] + return [RequestParameter.string(address), RequestParameter.string(string)] - case .call(let transactionParameters): - return [RequestParameter.transaction(transactionParameters)] + case .call(let transactionParameters, let blockNumber): + return [RequestParameter.transaction(transactionParameters), RequestParameter.string(blockNumber.stringValue)] case .getTransactionCount(let address, let blockNumber): return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] @@ -169,10 +188,10 @@ extension APIRequest { return [RequestParameter.string(uInt.hexString), RequestParameter.string(blockNumber.stringValue), RequestParameter.doubleArray(array)] case .createAccount(let string): - return [RequestParameter]() + return [RequestParameter.string(string)] - case .unlockAccount(let address, let string, let optional): - return [RequestParameter]() + case .unlockAccount(let address, let string, let uInt): + return [RequestParameter.string(address), RequestParameter.string(string), RequestParameter.uint(uInt ?? 0)] case .getTxPoolStatus: return [RequestParameter]() diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift new file mode 100755 index 000000000..f38400369 --- /dev/null +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift @@ -0,0 +1,20 @@ +// web3swift +// +// Created by Alex Vlasov. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// + +import Foundation + + +extension web3.Eth { + + // FIXME: Possible this not working at all. + public func callTransaction(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions?) async throws -> Data { + // FIXME: Add appropriate error + guard let transactionParameters = transaction.encodeAsDictionary(from: transactionOptions?.from) else { throw Web3Error.unknownError} + let request: APIRequest = .call(transactionParameters, transactionOptions?.callOnBlock ?? .latest) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) + return response.result + } +} diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift new file mode 100755 index 000000000..8ec738667 --- /dev/null +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift @@ -0,0 +1,36 @@ +// web3swift +// +// Created by Alex Vlasov. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// + +import Foundation +import BigInt + + +extension web3.Eth { + + public func estimateGas(for transaction: EthereumTransaction, transactionOptions: TransactionOptions?) async throws -> BigUInt { + // FIXME: Add appropriate error + guard let transactionParameters = transaction.encodeAsDictionary(from: transactionOptions?.from) else { throw Web3Error.unknownError } + + let request: APIRequest = .estimateGas(transactionParameters, transactionOptions?.callOnBlock ?? .latest) + let response: APIResponse = try await APIRequest.sendRequest(with: provider, for: request) + + if let policy = transactionOptions?.gasLimit { + switch policy { + case .automatic: + return response.result + case .limited(let limitValue): + return limitValue < response.result ? limitValue: response.result + case .manual(let exactValue): + return exactValue + case .withMargin: + // MARK: - update value according margin + return response.result + } + } else { + return response.result + } + } +} diff --git a/Sources/web3swift/EthereumAPICalls/Eth+FeeHistory.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+FeeHistory.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetAccounts.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetAccounts.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetBalance.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetBalance.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetBlockByHash.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetBlockByHash.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetBlockByNumber.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetBlockByNumber.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetBlockNumber.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetBlockNumber.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetCode.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetCode.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetGasPrice.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetGasPrice.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetTransactionCount.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetTransactionCount.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift new file mode 100755 index 000000000..9adbd15e8 --- /dev/null +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift @@ -0,0 +1,22 @@ +// web3swift +// +// Created by Alex Vlasov. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// + +import Foundation +import BigInt + +extension TransactionDetails: APIResultType { } + +extension web3.Eth { + public func transactionDetails(_ txhash: Data) async throws -> TransactionDetails { + try await self.transactionDetails(txhash.toHexString().addHexPrefix()) + } + + public func transactionDetails(_ txhash: Hash) async throws -> TransactionDetails { + let requestCall: APIRequest = .getTransactionByHash(txhash) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: requestCall) + return response.result + } +} diff --git a/Sources/web3swift/EthereumAPICalls/Eth+GetTransactionReceipt.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Eth+GetTransactionReceipt.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendRawTransaction.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift similarity index 58% rename from Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendRawTransaction.swift rename to Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift index 9332b575a..601714ab8 100755 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendRawTransaction.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift @@ -16,25 +16,15 @@ extension web3.Eth { } public func send(raw transaction: EthereumTransaction) async throws -> TransactionSendingResult { + // FIXME: Add appropriate error + guard let transactionHexData = transaction.encode()?.toHexString().addHexPrefix() else { throw Web3Error.unknownError } + let request: APIRequest = .sendRawTransaction(transactionHexData) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) - guard let request = EthereumTransaction.createRawTransaction(transaction: transaction) else { - throw Web3Error.processingError(desc: "Transaction is invalid") - } - let response = try await web3.dispatch(request) - - - guard let value: String = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - let result = TransactionSendingResult(transaction: transaction, hash: value) + let result = TransactionSendingResult(transaction: transaction, hash: response.result) for hook in self.web3.postSubmissionHooks { hook.function(result) } return result - - } } diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift new file mode 100755 index 000000000..c8aed56ba --- /dev/null +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift @@ -0,0 +1,61 @@ +// web3swift +// +// Created by Alex Vlasov. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// + +import Foundation +import BigInt + + +extension web3.Eth { + + public func send(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions? = nil, password: String = "web3swift") async throws -> TransactionSendingResult { + // print(transaction) + var assembledTransaction: EthereumTransaction = transaction + + var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) + + var forAssemblyPipeline: (EthereumTransaction, TransactionOptions) = (assembledTransaction, mergedOptions) + + for hook in self.web3.preSubmissionHooks { + let hookResult = hook.function(forAssemblyPipeline) + if hookResult.2 { + forAssemblyPipeline = (hookResult.0, hookResult.1) + } + + let shouldContinue = hookResult.2 + if !shouldContinue { + throw Web3Error.processingError(desc: "Transaction is canceled by middleware") + } + } + + assembledTransaction = forAssemblyPipeline.0 + mergedOptions = forAssemblyPipeline.1 + + + if let attachedKeystoreManager = self.web3.provider.attachedKeystoreManager { + guard let from = mergedOptions.from else { + throw Web3Error.inputError(desc: "No 'from' field provided") + } + do { + try Web3Signer.signTX(transaction: &assembledTransaction, keystore: attachedKeystoreManager, account: from, password: password) + } catch { + throw Web3Error.inputError(desc: "Failed to locally sign a transaction") + } + return try await self.web3.eth.send(raw: assembledTransaction) + } + + // FIXME: Add appropriate error + guard let transactionParameters = transaction.encodeAsDictionary(from: transactionOptions?.from) else { throw Web3Error.unknownError } + + let request: APIRequest = .sendTransaction(transactionParameters, transactionOptions?.callOnBlock ?? .latest) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) + + let result = TransactionSendingResult(transaction: assembledTransaction, hash: response.result) + for hook in self.web3.postSubmissionHooks { + hook.function(result) + } + return result + } +} diff --git a/Sources/web3swift/EthereumAPICalls/Personal+CreateAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Personal+CreateAccount.swift rename to Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Personal+Sign.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift similarity index 58% rename from Sources/web3swift/EthereumAPICalls/Promise+Web3+Personal+Sign.swift rename to Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift index e609baf97..5483a47c7 100755 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Personal+Sign.swift +++ b/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift @@ -10,24 +10,16 @@ import BigInt extension web3.Personal { + // FIXME: Possible this not working at all. public func signPersonal(message: Data, from: EthereumAddress, password: String = "web3swift") async throws -> Data { guard let attachedKeystoreManager = self.web3.provider.attachedKeystoreManager else { let hexData = message.toHexString().addHexPrefix() - let request = JSONRPCRequestFabric.prepareRequest(.personalSign, parameters: [from.address.lowercased(), hexData]) - - let response = try await self.web3.dispatch(request) - - guard let value: Data = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value + let request: APIRequest = .personalSign(from.address.lowercased(), hexData) + let response: APIResponse = try await APIRequest.sendRequest(with: provider, for: request) + return response.result } - guard let signature = try Web3Signer.signPersonalMessage(message, keystore: attachedKeystoreManager, account: from, password: password) else { throw Web3Error.inputError(desc: "Failed to locally sign a message") } diff --git a/Sources/web3swift/EthereumAPICalls/Personal+UnlockAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift similarity index 100% rename from Sources/web3swift/EthereumAPICalls/Personal+UnlockAccount.swift rename to Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift deleted file mode 100755 index 4e0d2a776..000000000 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+Call.swift +++ /dev/null @@ -1,26 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation - - -extension web3.Eth { - - public func callTransaction(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions?) async throws -> Data { - guard let request = EthereumTransaction.createRequest(method: .call, transaction: transaction, transactionOptions: transactionOptions) else { - throw Web3Error.processingError(desc: "Transaction is invalid") - } - let response = try await web3.dispatch(request) - - guard let value: Data = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - } -} diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift deleted file mode 100755 index 96e10645b..000000000 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+EstimateGas.swift +++ /dev/null @@ -1,45 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - - -extension web3.Eth { - - public func estimateGas(for transaction: EthereumTransaction, transactionOptions: TransactionOptions?) async throws -> BigUInt { - - guard let request = EthereumTransaction.createRequest(method: .estimateGas, transaction: transaction, transactionOptions: transactionOptions) else { - throw Web3Error.processingError(desc: "Transaction is invalid") - } - let response = try await web3.dispatch(request) - - guard let value: BigUInt = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - - if let policy = transactionOptions?.gasLimit { - switch policy { - case .automatic: - return value - case .limited(let limitValue): - return limitValue < value ? limitValue: value - case .manual(let exactValue): - return exactValue - case .withMargin: - // MARK: - update value according margin - return value - } - } else { - return value - } - - - } -} diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift deleted file mode 100755 index 4119a2c0b..000000000 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+GetTransactionDetails.swift +++ /dev/null @@ -1,30 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - - -extension web3.Eth { - public func transactionDetails(_ txhash: Data) async throws -> TransactionDetails { - let hashString = txhash.toHexString().addHexPrefix() - return try await self.transactionDetails(hashString) - } - - public func transactionDetails(_ txhash: String) async throws -> TransactionDetails { - let request = JSONRPCRequestFabric.prepareRequest(.getTransactionByHash, parameters: [txhash]) - let response = try await web3.dispatch(request) - - guard let value: TransactionDetails = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - - } -} diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift deleted file mode 100755 index 86d90e344..000000000 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+Eth+SendTransaction.swift +++ /dev/null @@ -1,69 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - - -extension web3.Eth { - - public func send(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions? = nil, password: String = "web3swift") async throws -> TransactionSendingResult { - // print(transaction) - var assembledTransaction: EthereumTransaction = transaction - - var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) - - var forAssemblyPipeline: (EthereumTransaction, TransactionOptions) = (assembledTransaction, mergedOptions) - - for hook in self.web3.preSubmissionHooks { - let hookResult = hook.function(forAssemblyPipeline) - if hookResult.2 { - forAssemblyPipeline = (hookResult.0, hookResult.1) - } - - let shouldContinue = hookResult.2 - if !shouldContinue { - throw Web3Error.processingError(desc: "Transaction is canceled by middleware") - } - } - - assembledTransaction = forAssemblyPipeline.0 - mergedOptions = forAssemblyPipeline.1 - - guard let attachedKeystoreManager = self.web3.provider.attachedKeystoreManager else { - guard let request = EthereumTransaction.createRequest(method: .sendTransaction, transaction: assembledTransaction, transactionOptions: mergedOptions) else - { - throw Web3Error.processingError(desc: "Failed to create a request to send transaction") - } - let response = try await self.web3.dispatch(request) - - guard let value: String = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - let result = TransactionSendingResult(transaction: assembledTransaction, hash: value) - for hook in self.web3.postSubmissionHooks { - Task { - hook.function(result) - } - } - return result - } - - guard let from = mergedOptions.from else { - throw Web3Error.inputError(desc: "No 'from' field provided") - } - do { - try Web3Signer.signTX(transaction: &assembledTransaction, keystore: attachedKeystoreManager, account: from, password: password) - } catch { - throw Web3Error.inputError(desc: "Failed to locally sign a transaction") - } - return try await self.web3.eth.send(raw: assembledTransaction) - - } -} diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/web3swift/Transaction/EthereumTransaction.swift index 700aeb302..534726015 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/web3swift/Transaction/EthereumTransaction.swift @@ -177,53 +177,10 @@ public struct EthereumTransaction: CustomStringConvertible { /// - Returns: a TransactionParameters object suitable for passing to Web3+JSONRPC provider public func encodeAsDictionary(from: EthereumAddress? = nil) -> TransactionParameters? { self.envelope.encodeAsDictionary(from: from) } - - // FIXME: Move this logic into place where it supposed to be. - /// create a JSON RPC Request object for the given transacton - /// - Parameters: - /// - method: RPC request method - /// - transaction: the transaction to encode/send - /// - transactionOptions: additional options for the transaction - /// - Returns: a JSONRPCrequest object - static func createRequest(method: JSONRPCmethod, transaction: EthereumTransaction, transactionOptions: TransactionOptions?) -> JSONRPCrequest? { - let onBlock = transactionOptions?.callOnBlock?.stringValue - var request = JSONRPCrequest() - - request.method = method - let from = transactionOptions?.from - guard var txParams = transaction.encodeAsDictionary(from: from) else { return nil } - if method == .estimateGas || transactionOptions?.gasLimit == nil { - txParams.gas = nil - } - var params: [RequestParameter] = [.transaction(txParams)] - if let onBlock = onBlock, method.requiredNumOfParameters == 2 { - params.append(.string(onBlock)) - } - request.params = params - if !request.isValid { return nil } - return request - } - /// - Returns: a raw bytestream of the transaction, encoded according to the transactionType func encode(for type: EncodeType = .transaction) -> Data? { return self.envelope.encode(for: type) } - - // FIXME: Move this logic into place where it supposed to be. - /// creates a Raw RPC request transaction for the given Transaction - /// - Parameter transaction: EthereumTransaction to encode - /// - Returns: a JSONRPCrequest object - static func createRawTransaction(transaction: EthereumTransaction) -> JSONRPCrequest? { - guard transaction.sender != nil else { return nil } - guard let encodedData = transaction.encode() else { return nil } - let hex = encodedData.toHexString().addHexPrefix().lowercased() - var request = JSONRPCrequest() - request.method = JSONRPCmethod.sendRawTransaction - let params: [RequestParameter] = [.string(hex)] - request.params = params - if !request.isValid { return nil } - return request - } } extension EthereumTransaction: Decodable { diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index 29494ced0..eb78d9eba 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -14,7 +14,7 @@ public enum BlockNumber { /// Earliest block of a chain case earliest /// Exact block number - case exact(UInt) + case exact(BigUInt) /// Block number as a hex string public var stringValue: String { @@ -128,7 +128,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { return socketProvider } - public func writeMessage(method: InfuraWebsocketMethod, params: [APIRequestParameterType]) throws { + public func writeMessage(method: InfuraWebsocketMethod, params: [Encodable]) throws { let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params) let encoder = JSONEncoder() let requestData = try encoder.encode(request) @@ -136,7 +136,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { writeMessage(requestData) } - public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [APIRequestParameterType]? = nil) throws { + public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -153,7 +153,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { try setFilterAndGetChanges(method: method, params: [filterParams]) } - public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [APIRequestParameterType]? = nil) throws { + public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { filterTimer?.invalidate() filterID = nil let params = params ?? [] @@ -204,7 +204,7 @@ public final class InfuraWebsocketProvider: WebsocketProvider { } } - public func subscribe(params: [APIRequestParameterType]) throws { + public func subscribe(params: [Encodable]) throws { let method = InfuraWebsocketMethod.subscribe try writeMessage(method: method, params: params) } diff --git a/Sources/web3swift/Web3/Web3+Options.swift b/Sources/web3swift/Web3/Web3+Options.swift index 1b0a26fb2..bba7fa3ea 100755 --- a/Sources/web3swift/Web3/Web3+Options.swift +++ b/Sources/web3swift/Web3/Web3+Options.swift @@ -67,24 +67,7 @@ public struct TransactionOptions { public var nonce: NoncePolicy? - public enum CallingBlockPolicy { - case pending - case latest - case exactBlockNumber(BigUInt) - - var stringValue: String { - switch self { - case .pending: - return "pending" - case .latest: - return "latest" - case .exactBlockNumber(let number): - return String(number, radix: 16).addHexPrefix() - } - } - } - - public var callOnBlock: CallingBlockPolicy? + public var callOnBlock: BlockNumber? public var accessList: [AccessListEntry]? @@ -274,7 +257,7 @@ extension TransactionOptions: Decodable { } if let callOnBlock = try? container.decodeHex(BigUInt.self, forKey: .callOnBlock) { - self.callOnBlock = .exactBlockNumber(callOnBlock) + self.callOnBlock = .exact(callOnBlock) } else { self.callOnBlock = defaultOptions.callOnBlock } From dddf1f2d6b8158cdb4320708fa9fd58aad944bb1 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 17:19:21 +0700 Subject: [PATCH 31/45] Rename `getTransactionCount(address:, onBlock:)` to `getTransactionCount(for:, onBlock:)` --- Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift | 2 +- Sources/web3swift/Utils/Hooks/NonceMiddleware.swift | 2 +- Sources/web3swift/Web3/Web3+MutatingTransaction.swift | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift index b9a39be2a..e8a7eec65 100755 --- a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift +++ b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift @@ -195,7 +195,7 @@ extension web3.BrowserFunctions { case .manual(let nonce): transaction.nonce = nonce default: - let nonce = try await self.web3.eth.getTransactionCount(address: from, onBlock: "pending") + let nonce = try await self.web3.eth.getTransactionCount(for: from, onBlock: .pending) transaction.nonce = nonce } diff --git a/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift b/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift index 3ad0f187b..daf9ed19a 100755 --- a/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift +++ b/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift @@ -30,7 +30,7 @@ extension Web3.Utils { knownKeys.forEach { key in group.addTask { - try? await w3.eth.getTransactionCount(address: key, onBlock: "latest") + try? await w3.eth.getTransactionCount(for: key, onBlock: .latest) } } diff --git a/Sources/web3swift/Web3/Web3+MutatingTransaction.swift b/Sources/web3swift/Web3/Web3+MutatingTransaction.swift index 3456d3734..54f31189c 100755 --- a/Sources/web3swift/Web3/Web3+MutatingTransaction.swift +++ b/Sources/web3swift/Web3/Web3+MutatingTransaction.swift @@ -209,9 +209,9 @@ public class WriteTransaction: ReadTransaction { func nonce(for policy: TransactionOptions.NoncePolicy, from: EthereumAddress) async throws -> BigUInt { switch policy { case .latest: - return try await self.web3.eth.getTransactionCount(address: from, onBlock: "latest") + return try await self.web3.eth.getTransactionCount(for: from, onBlock: .latest) case .pending: - return try await self.web3.eth.getTransactionCount(address: from, onBlock: "pending") + return try await self.web3.eth.getTransactionCount(for: from, onBlock: .pending) case .manual(let nonce): return nonce } From 65c5a53a2e219643b7fdd9800a59631d44a1f7ab Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 18:10:26 +0700 Subject: [PATCH 32/45] Add TxPool and getLog implementation - Temporary disabled getting Network within Web3HttpProvider init. - --- Sources/web3swift/API/APIMethod.swift | 17 +--- .../Promise+Web3+TxPool.swift | 53 ---------- .../web3swift/EthereumAPICalls/TxPool.swift | 35 +++++++ Sources/web3swift/Web3/Web3+EventParser.swift | 83 +++++++--------- .../web3swift/Web3/Web3+HttpProvider.swift | 96 +++++++------------ Sources/web3swift/Web3/Web3+Structures.swift | 6 ++ Sources/web3swift/Web3/Web3.swift | 3 +- 7 files changed, 117 insertions(+), 176 deletions(-) delete mode 100755 Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift create mode 100755 Sources/web3swift/EthereumAPICalls/TxPool.swift diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 0cf4ad740..559400e1d 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -117,14 +117,14 @@ extension APIRequest { case .estimateGas: return BigUInt.self case .call: return Data.self // FIXME: Not checked - case .getNetwork: return UInt.self + case .getNetwork: return Int.self case .personalSign: return Data.self + case .getTxPoolStatus: return TxPoolStatus.self + case .getTxPoolContent: return TxPoolContent.self // FIXME: Not implemented case .getLogs: return String.self case .getStorageAt: return String.self - case .getTxPoolStatus: return String.self - case .getTxPoolContent: return String.self case .getTxPoolInspect: return String.self } } @@ -138,7 +138,7 @@ extension APIRequest { var parameters: [RequestParameter] { switch self { - case .gasPrice, .blockNumber, .getNetwork, .getAccounts: + case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .getTxPoolStatus, .getTxPoolContent, .getTxPoolInspect: return [RequestParameter]() case .estimateGas(let transactionParameters, let blockNumber): @@ -192,15 +192,6 @@ extension APIRequest { case .unlockAccount(let address, let string, let uInt): return [RequestParameter.string(address), RequestParameter.string(string), RequestParameter.uint(uInt ?? 0)] - - case .getTxPoolStatus: - return [RequestParameter]() - - case .getTxPoolContent: - return [RequestParameter]() - - case .getTxPoolInspect: - return [RequestParameter]() } } diff --git a/Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift b/Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift deleted file mode 100755 index 74bbfcaf8..000000000 --- a/Sources/web3swift/EthereumAPICalls/Promise+Web3+TxPool.swift +++ /dev/null @@ -1,53 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - - -extension web3.TxPool { - public func txPoolInspect() async throws -> [String: [String: [String: String]]] { - let request = JSONRPCRequestFabric.prepareRequest(.getTxPoolInspect, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: [String: [String: [String: String]]] = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - - } - - public func txPoolStatus() async throws -> TxPoolStatus { - let request = JSONRPCRequestFabric.prepareRequest(.getTxPoolStatus, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: TxPoolStatus = response.result as? TxPoolStatus else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - - } - - public func txPoolContent() async throws -> TxPoolContent { - let request = JSONRPCRequestFabric.prepareRequest(.getTxPoolContent, parameters: []) - let response = try await web3.dispatch(request) - - guard let value: TxPoolContent = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") - } - return value - - } -} diff --git a/Sources/web3swift/EthereumAPICalls/TxPool.swift b/Sources/web3swift/EthereumAPICalls/TxPool.swift new file mode 100755 index 000000000..084375774 --- /dev/null +++ b/Sources/web3swift/EthereumAPICalls/TxPool.swift @@ -0,0 +1,35 @@ +// web3swift +// +// Created by Alex Vlasov. +// Copyright © 2018 Alex Vlasov. All rights reserved. +// + +import Foundation +import BigInt + + +extension web3.TxPool { +// public func txPoolInspect() async throws -> [String: [String: [String: String]]] { +// let request = JSONRPCRequestFabric.prepareRequest(.getTxPoolInspect, parameters: []) +// let response = try await web3.dispatch(request) +// +// guard let value: [String: [String: [String: String]]] = response.getValue() else { +// if response.error != nil { +// throw Web3Error.nodeError(desc: response.error!.message) +// } +// throw Web3Error.nodeError(desc: "Invalid value from Ethereum node") +// } +// return value +// +// } + + public func txPoolStatus() async throws -> TxPoolStatus { + let response: APIResponse = try await APIRequest.sendRequest(with: provider, for: .getTxPoolStatus) + return response.result + } + + public func txPoolContent() async throws -> TxPoolContent { + let response: APIResponse = try await APIRequest.sendRequest(with: provider, for: .getTxPoolContent) + return response.result + } +} diff --git a/Sources/web3swift/Web3/Web3+EventParser.swift b/Sources/web3swift/Web3/Web3+EventParser.swift index 5a47fb2c8..1e161e72b 100755 --- a/Sources/web3swift/Web3/Web3+EventParser.swift +++ b/Sources/web3swift/Web3/Web3+EventParser.swift @@ -28,10 +28,10 @@ extension web3.web3contract { *Parses the block for events matching the EventParser settings.* - parameters: - - blockNumber: Ethereum network block number + - blockNumber: Ethereum network block number - returns: - - Result object + - Result object - important: This call is synchronous @@ -45,10 +45,10 @@ extension web3.web3contract { *Parses the block for events matching the EventParser settings.* - parameters: - - block: Native web3swift block object + - block: Native web3swift block object - returns: - - Result object + - Result object - important: This call is synchronous @@ -62,10 +62,10 @@ extension web3.web3contract { *Parses the transaction for events matching the EventParser settings.* - parameters: - - hash: Transaction hash + - hash: Transaction hash - returns: - - Result object + - Result object - important: This call is synchronous @@ -79,10 +79,10 @@ extension web3.web3contract { *Parses the transaction for events matching the EventParser settings.* - parameters: - - transaction: web3swift native EthereumTransaction object + - transaction: web3swift native EthereumTransaction object - returns: - - Result object + - Result object - important: This call is synchronous @@ -174,65 +174,49 @@ extension web3.web3contract.EventParser { } extension web3.web3contract { - /** *Fetches events by doing a lookup on "indexed" parameters of the event. Smart-contract developer can make some of event values "indexed" for such fast queries.* - parameters: - - eventName: Event name, should be present in ABI interface of the contract - - filter: EventFilter object setting the block limits for query - - joinWithReceipts: Bool indicating whether TransactionReceipt should be fetched separately for every matched transaction + - eventName: Event name, should be present in ABI interface of the contract + - filter: EventFilter object setting the block limits for query + - joinWithReceipts: Bool indicating whether TransactionReceipt should be fetched separately for every matched transaction - returns: - - Result object + - Result object - important: This call is synchronous */ public func getIndexedEvents(eventName: String?, filter: EventFilter, joinWithReceipts: Bool = false) async throws -> [EventParserResultProtocol] { - let result = try await self.getIndexedEventsPromise(eventName: eventName, filter: filter, joinWithReceipts: joinWithReceipts) - return result - } -} - -extension web3.web3contract { - public func getIndexedEventsPromise(eventName: String?, filter: EventFilter, joinWithReceipts: Bool = false) async throws -> [EventParserResultProtocol] { - - let rawContract = self.contract - guard let preEncoding = encodeTopicToGetLogs(contract: rawContract, eventName: eventName, filter: filter) else { - throw Web3Error.processingError(desc: "Failed to encode topic for request") - } - - if eventName != nil { - guard let _ = rawContract.events[eventName!] else { - throw Web3Error.processingError(desc: "No such event in a contract") - } - } - let request = JSONRPCRequestFabric.prepareRequest(.getLogs, parameters: [preEncoding]) - let response = try await self.web3.dispatch(request) + let rawContract = self.contract + guard let preEncoding = encodeTopicToGetLogs(contract: rawContract, eventName: eventName, filter: filter) else { + throw Web3Error.processingError(desc: "Failed to encode topic for request") + } - guard let allLogs: [EventLog] = response.getValue() else { - if response.error != nil { - throw Web3Error.nodeError(desc: response.error!.message) - } - throw Web3Error.nodeError(desc: "Empty or malformed response") + if eventName != nil { + guard let _ = rawContract.events[eventName!] else { + throw Web3Error.processingError(desc: "No such event in a contract") } + } + // FIXME: This could not worked at all. + let request: APIRequest = .getLogs(preEncoding) + let response: APIResponse<[EventLog]> = try await APIRequest.sendRequest(with: self.web3.provider, for: request) - let decodedLogs = allLogs.compactMap { (log) -> EventParserResult? in - let (n, d) = self.contract.parseEvent(log) - guard let evName = n, let evData = d else {return nil} - var res = EventParserResult(eventName: evName, transactionReceipt: nil, contractAddress: log.address, decodedResult: evData) - res.eventLog = log - return res - } + let decodedLogs = response.result.compactMap { (log) -> EventParserResult? in + let (n, d) = self.contract.parseEvent(log) + guard let evName = n, let evData = d else {return nil} + var res = EventParserResult(eventName: evName, transactionReceipt: nil, contractAddress: log.address, decodedResult: evData) + res.eventLog = log + return res + } .filter{ res in res.eventLog != nil || (res.eventName == eventName && eventName != nil)} - if (!joinWithReceipts) { - return decodedLogs as [EventParserResultProtocol] - } - + if (!joinWithReceipts) { + return decodedLogs as [EventParserResultProtocol] + } return await withTaskGroup(of: EventParserResultProtocol.self, returning: [EventParserResultProtocol].self) { group -> [EventParserResultProtocol] in @@ -252,7 +236,6 @@ extension web3.web3contract { } return collected - } } } diff --git a/Sources/web3swift/Web3/Web3+HttpProvider.swift b/Sources/web3swift/Web3/Web3+HttpProvider.swift index d0a545822..dfc52bc5b 100755 --- a/Sources/web3swift/Web3/Web3+HttpProvider.swift +++ b/Sources/web3swift/Web3/Web3+HttpProvider.swift @@ -10,8 +10,8 @@ import BigInt /// Providers abstraction for custom providers (websockets, other custom private key managers). At the moment should not be used. public protocol Web3Provider { - func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse - func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch +// func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse +// func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch var network: Networks? {get set} var attachedKeystoreManager: KeystoreManager? {get set} var url: URL {get} @@ -28,66 +28,44 @@ public class Web3HttpProvider: Web3Provider { let urlSession = URLSession(configuration: config) return urlSession }() - public init?(_ httpProviderURL: URL, network net: Networks? = nil, keystoreManager manager: KeystoreManager? = nil) async { - do { - guard httpProviderURL.scheme == "http" || httpProviderURL.scheme == "https" else { - return nil - } - url = httpProviderURL - if net == nil { - let request = JSONRPCRequestFabric.prepareRequest(.getNetwork, parameters: []) - let response: JSONRPCresponse = try await Web3HttpProvider.post(request, providerURL: httpProviderURL, session: session) - if response.error != nil { - if response.message != nil { - print(response.message!) - } - return nil - } - guard let result: String = response.getValue(), let intNetworkNumber = Int(result) else {return nil} - network = Networks.fromInt(intNetworkNumber) - if network == nil { - return nil - } - } else { - network = net - } - } catch { - return nil - } + public init?(_ httpProviderURL: URL, network net: Networks, keystoreManager manager: KeystoreManager? = nil) { + guard httpProviderURL.scheme == "http" || httpProviderURL.scheme == "https" else { return nil } + url = httpProviderURL + network = net attachedKeystoreManager = manager } - fileprivate static func dataFrom(session: URLSession, request urlRequest: URLRequest) async throws -> Data{ - let (data, _) = try await session.data(for: urlRequest) - return data - } - - static func post(_ request: U, providerURL: URL, session: URLSession) async throws -> T { - let requestData = try JSONEncoder().encode(request) - var urlRequest = URLRequest(url: providerURL, cachePolicy: .reloadIgnoringCacheData) - urlRequest.httpMethod = "POST" - urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") - urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") - urlRequest.httpBody = requestData - - let data = try await dataFrom(session: session, request: urlRequest) - - let parsedResponse = try JSONDecoder().decode(T.self, from: data) - - if let response = parsedResponse as? JSONRPCresponse, response.error != nil { - throw Web3Error.nodeError(desc: "Received an error message from node\n" + String(describing: response.error!)) - } - return parsedResponse - - } - - public func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { - guard request.method != nil else { - throw Web3Error.nodeError(desc: "RPC method is nill") - } - - return try await Web3HttpProvider.post(request, providerURL: self.url, session: self.session) - } +// fileprivate static func dataFrom(session: URLSession, request urlRequest: URLRequest) async throws -> Data{ +// let (data, _) = try await session.data(for: urlRequest) +// return data +// } +// +// static func post(_ request: U, providerURL: URL, session: URLSession) async throws -> T { +// let requestData = try JSONEncoder().encode(request) +// var urlRequest = URLRequest(url: providerURL, cachePolicy: .reloadIgnoringCacheData) +// urlRequest.httpMethod = "POST" +// urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") +// urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") +// urlRequest.httpBody = requestData +// +// let data = try await dataFrom(session: session, request: urlRequest) +// +// let parsedResponse = try JSONDecoder().decode(T.self, from: data) +// +// if let response = parsedResponse as? JSONRPCresponse, response.error != nil { +// throw Web3Error.nodeError(desc: "Received an error message from node\n" + String(describing: response.error!)) +// } +// return parsedResponse +// +// } +// +// public func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { +// guard request.method != nil else { +// throw Web3Error.nodeError(desc: "RPC method is nill") +// } +// +// return try await Web3HttpProvider.post(request, providerURL: self.url, session: self.session) +// } // public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { // return try await Web3HttpProvider.post(requests, providerURL: self.url, session: self.session) diff --git a/Sources/web3swift/Web3/Web3+Structures.swift b/Sources/web3swift/Web3/Web3+Structures.swift index 9792a768d..8971c2c6e 100755 --- a/Sources/web3swift/Web3/Web3+Structures.swift +++ b/Sources/web3swift/Web3/Web3+Structures.swift @@ -174,6 +174,8 @@ public struct EventLog: Decodable { } } +extension EventLog: APIResultType { } + public enum TransactionInBlock: Decodable { case hash(Data) case transaction(EthereumTransaction) @@ -316,6 +318,8 @@ public struct TxPoolStatus: Decodable { } } +extension TxPoolStatus: APIResultType { } + public extension TxPoolStatus { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) @@ -377,6 +381,8 @@ public struct TxPoolContent: Decodable { } } +extension TxPoolContent: APIResultType { } + extension TxPoolContent { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) diff --git a/Sources/web3swift/Web3/Web3.swift b/Sources/web3swift/Web3/Web3.swift index 281d8f0ee..04be07dc5 100755 --- a/Sources/web3swift/Web3/Web3.swift +++ b/Sources/web3swift/Web3/Web3.swift @@ -52,7 +52,8 @@ public struct Web3 { /// Initialized provider-bound Web3 instance using a provider's URL. Under the hood it performs a synchronous call to get /// the Network ID for EIP155 purposes public static func new(_ providerURL: URL) async throws -> web3 { - guard let provider = await Web3HttpProvider(providerURL) else { + // FIXME: Change this hardcoded value to dynamicly fethed from a Node + guard let provider = await Web3HttpProvider(providerURL, network: .Mainnet) else { throw Web3Error.inputError(desc: "Wrong provider - should be Web3HttpProvider with endpoint scheme http or https") } return web3(provider: provider) From b24948f9d2470e9f7c63aa3859802527424b727c Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 18:14:05 +0700 Subject: [PATCH 33/45] Temporary disable Websocket provider. --- .../web3swift/Web3/Web3+Eth+Websocket.swift | 54 +- .../web3swift/Web3/Web3+InfuraProviders.swift | 560 +++++++++--------- .../Web3/Web3+WebsocketProvider.swift | 450 +++++++------- 3 files changed, 532 insertions(+), 532 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+Eth+Websocket.swift b/Sources/web3swift/Web3/Web3+Eth+Websocket.swift index a09acfa55..b5cbbc172 100644 --- a/Sources/web3swift/Web3/Web3+Eth+Websocket.swift +++ b/Sources/web3swift/Web3/Web3+Eth+Websocket.swift @@ -11,31 +11,31 @@ import BigInt import Starscream extension web3.Eth { - - public func getWebsocketProvider(forDelegate delegate: Web3SocketDelegate) throws -> InfuraWebsocketProvider { - var infuraWSProvider: InfuraWebsocketProvider - if !(provider is InfuraWebsocketProvider) { - guard let infuraNetwork = provider.network else { - throw Web3Error.processingError(desc: "Wrong network") - } - guard let infuraProvider = InfuraWebsocketProvider(infuraNetwork, delegate: delegate, keystoreManager: provider.attachedKeystoreManager) else { - throw Web3Error.processingError(desc: "Wrong network") - } - infuraWSProvider = infuraProvider - } else { - infuraWSProvider = provider as! InfuraWebsocketProvider - } - infuraWSProvider.connectSocket() - return infuraWSProvider - } - - public func getLatestPendingTransactions(forDelegate delegate: Web3SocketDelegate) throws { - let provider = try getWebsocketProvider(forDelegate: delegate) - try provider.setFilterAndGetChanges(method: .newPendingTransactionFilter) - } - - public func subscribeOnPendingTransactions(forDelegate delegate: Web3SocketDelegate) throws { - let provider = try getWebsocketProvider(forDelegate: delegate) - try provider.subscribeOnNewPendingTransactions() - } +// +// public func getWebsocketProvider(forDelegate delegate: Web3SocketDelegate) throws -> InfuraWebsocketProvider { +// var infuraWSProvider: InfuraWebsocketProvider +// if !(provider is InfuraWebsocketProvider) { +// guard let infuraNetwork = provider.network else { +// throw Web3Error.processingError(desc: "Wrong network") +// } +// guard let infuraProvider = InfuraWebsocketProvider(infuraNetwork, delegate: delegate, keystoreManager: provider.attachedKeystoreManager) else { +// throw Web3Error.processingError(desc: "Wrong network") +// } +// infuraWSProvider = infuraProvider +// } else { +// infuraWSProvider = provider as! InfuraWebsocketProvider +// } +// infuraWSProvider.connectSocket() +// return infuraWSProvider +// } +// +// public func getLatestPendingTransactions(forDelegate delegate: Web3SocketDelegate) throws { +// let provider = try getWebsocketProvider(forDelegate: delegate) +// try provider.setFilterAndGetChanges(method: .newPendingTransactionFilter) +// } +// +// public func subscribeOnPendingTransactions(forDelegate delegate: Web3SocketDelegate) throws { +// let provider = try getWebsocketProvider(forDelegate: delegate) +// try provider.subscribeOnNewPendingTransactions() +// } } diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index eb78d9eba..7d2959bf1 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -41,283 +41,283 @@ public final class InfuraProvider: Web3HttpProvider { } } -/// Custom Websocket provider of Infura nodes. -public final class InfuraWebsocketProvider: WebsocketProvider { - public var filterID: String? - public var subscriptionIDs = Set() - private var subscriptionIDforUnsubscribing: String? = nil - private var filterTimer: Timer? - - /// if set debugMode True then show websocket events logs in the console - public var debugMode: Bool = false - - public init?(_ network: Networks, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil) { - guard network == Networks.Kovan - || network == Networks.Rinkeby - || network == Networks.Ropsten - || network == Networks.Mainnet else {return nil} - let networkName = network.name - let urlString = "wss://" + networkName + Constants.infuraWsScheme - guard URL(string: urlString) != nil else {return nil} - super.init(urlString, - delegate: delegate, - projectId: projectId, - keystoreManager: manager, - network: network) - } - - public init?(_ endpoint: String, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil) { - guard URL(string: endpoint) != nil else {return nil} - super.init(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager) - } - - public init?(_ endpoint: URL, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil) { - super.init(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager) - } - - override public class func connectToSocket(_ endpoint: String, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) -> WebsocketProvider? { - guard let socketProvider = InfuraWebsocketProvider(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager) else {return nil} - socketProvider.connectSocket() - return socketProvider - } - - override public class func connectToSocket(_ endpoint: URL, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) -> WebsocketProvider? { - guard let socketProvider = InfuraWebsocketProvider(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager) else {return nil} - socketProvider.connectSocket() - return socketProvider - } - - public static func connectToInfuraSocket(_ network: Networks, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil) -> InfuraWebsocketProvider? { - guard let socketProvider = InfuraWebsocketProvider(network, - delegate: delegate, - projectId: projectId, - keystoreManager: manager) else {return nil} - socketProvider.connectSocket() - return socketProvider - } - - public func writeMessage(method: InfuraWebsocketMethod, params: [Encodable]) throws { - let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params) - let encoder = JSONEncoder() - let requestData = try encoder.encode(request) - print(String(decoding: requestData, as: UTF8.self)) - writeMessage(requestData) - } - - public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { - filterTimer?.invalidate() - filterID = nil - let params = params ?? [] - let paramsCount = params.count - guard method.requiredNumOfParameters == paramsCount || method.requiredNumOfParameters == nil else { - throw Web3Error.inputError(desc: "Wrong number of params: need - \(method.requiredNumOfParameters!), got - \(paramsCount)") - } - try writeMessage(method: method, params: params) - filterTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(getFilterChanges), userInfo: nil, repeats: true) - } - - public func setFilterAndGetChanges(method: InfuraWebsocketMethod, address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { - let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) - try setFilterAndGetChanges(method: method, params: [filterParams]) - } - - public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { - filterTimer?.invalidate() - filterID = nil - let params = params ?? [] - let paramsCount = params.count - guard method.requiredNumOfParameters == paramsCount || method.requiredNumOfParameters == nil else { - throw Web3Error.inputError(desc: "Wrong number of params: need - \(method.requiredNumOfParameters!), got - \(paramsCount)") - } - try writeMessage(method: method, params: params) - filterTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(getFilterLogs), userInfo: nil, repeats: true) - } - - public func setFilterAndGetLogs(method: InfuraWebsocketMethod, address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { - let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) - try setFilterAndGetLogs(method: method, params: [filterParams]) - } - - @objc public func getFilterChanges() throws { - if let id = filterID { - filterTimer?.invalidate() - let method = InfuraWebsocketMethod.getFilterChanges - try writeMessage(method: method, params: [id]) - } - } - - @objc public func getFilterLogs() throws { - if let id = filterID { - filterTimer?.invalidate() - let method = InfuraWebsocketMethod.getFilterLogs - try writeMessage(method: method, params: [id]) - } - } - - public func getFilterLogs(address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { - if let id = filterID { - let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) - let method = InfuraWebsocketMethod.getFilterLogs - try writeMessage(method: method, params: [id, filterParams]) - } - } - - public func unistallFilter() throws { - if let id = filterID { - filterID = nil - let method = InfuraWebsocketMethod.uninstallFilter - try writeMessage(method: method, params: [id]) - } else { - throw Web3Error.nodeError(desc: "No filter set") - } - } - - public func subscribe(params: [Encodable]) throws { - let method = InfuraWebsocketMethod.subscribe - try writeMessage(method: method, params: params) - } - - public func unsubscribe(subscriptionID: String) throws { - let method = InfuraWebsocketMethod.unsubscribe - subscriptionIDforUnsubscribing = subscriptionID - try writeMessage(method: method, params: [subscriptionID]) - } - - public func subscribeOnNewHeads() throws { - let method = InfuraWebsocketMethod.subscribe - let params = ["newHeads"] - try writeMessage(method: method, params: params) - } - - public func subscribeOnLogs(addresses: [EthereumAddress]? = nil, topics: [String]? = nil) throws { - let method = InfuraWebsocketMethod.subscribe - var stringAddresses = [String]() - if let addrs = addresses { - for addr in addrs { - stringAddresses.append(addr.address) - } - } -// let ts = topics == nil ? nil: [topics!] - let filterParams = EventFilterParameters(fromBlock: nil, toBlock: nil, topics: [topics], address: stringAddresses) - try writeMessage(method: method, params: ["logs", filterParams]) - } - - public func subscribeOnNewPendingTransactions() throws { - let method = InfuraWebsocketMethod.subscribe - let params = ["newPendingTransactions"] - try writeMessage(method: method, params: params) - } - - public func subscribeOnSyncing() throws { - guard network != Networks.Kovan else { - throw Web3Error.inputError(desc: "Can't sync on Kovan") - } - let method = InfuraWebsocketMethod.subscribe - let params = ["syncing"] - try writeMessage(method: method, params: params) - } - - /// override WebsocketDelegate - override public func didReceive(event: WebSocketEvent, client: WebSocket) { - switch event { - case .connected(let headers): - debugMode ? print("websocket is connected, headers:\n \(headers)") : nil - websocketConnected = true - delegate.socketConnected(headers) - case .disconnected(let reason, let code): - debugMode ? print("websocket is disconnected: \(reason) with code: \(code)") : nil - websocketConnected = false - delegate.gotError(error: Web3Error.connectionError) - case .text(let string): - debugMode ? print("received text: \(string)") : nil - websocketDidReceiveMessage(text: string) - break - case .binary(let data): - debugMode ? print("received text: \(String(data: data, encoding: .utf8) ?? "empty")") : nil - delegate.received(message: data) - case .ping(_): - debugMode ? print("ping") : nil - break - case .pong(_): - debugMode ? print("pong") : nil - break - case .viabilityChanged(_): - debugMode ? print("viabilityChanged") : nil - break - case .reconnectSuggested(_): - debugMode ? print("reconnectSuggested") : nil - break - case .cancelled: - debugMode ? print("cancelled") : nil - websocketConnected = false - delegate.gotError(error: Web3Error.nodeError(desc: "socket cancelled")) - case .error(let error): - debugMode ? print("error: \(String(describing: error))") : nil - websocketConnected = false - delegate.gotError(error: error!) - } - } - - private func websocketDidReceiveMessage(text: String) { - if let data = text.data(using: String.Encoding.utf8), - let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { - if filterID == nil, - let result = dictionary["result"] as? String { - // setting filter id - filterID = result - } else if let params = dictionary["params"] as? [String: Any], - let subscription = params["subscription"] as? String, - let result = params["result"] { - // subscription result - subscriptionIDs.insert(subscription) - delegate.received(message: result) - } else if let unsubscribed = dictionary["result"] as? Bool { - // unsubsribe result - if unsubscribed == true, let id = subscriptionIDforUnsubscribing { - subscriptionIDs.remove(id) - } else if let id = subscriptionIDforUnsubscribing { - delegate.gotError(error: Web3Error.processingError(desc: "Can\'t unsubscribe \(id)")) - } else { - delegate.received(message: unsubscribed) - } - } else if let message = dictionary["result"] { - // filter result - delegate.received(message: message) - } else { - delegate.gotError(error: Web3Error.processingError(desc: "Can\'t get known result. Message is: \(text)")) - } - } - } -} +///// Custom Websocket provider of Infura nodes. +//public final class InfuraWebsocketProvider: WebsocketProvider { +// public var filterID: String? +// public var subscriptionIDs = Set() +// private var subscriptionIDforUnsubscribing: String? = nil +// private var filterTimer: Timer? +// +// /// if set debugMode True then show websocket events logs in the console +// public var debugMode: Bool = false +// +// public init?(_ network: Networks, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil) { +// guard network == Networks.Kovan +// || network == Networks.Rinkeby +// || network == Networks.Ropsten +// || network == Networks.Mainnet else {return nil} +// let networkName = network.name +// let urlString = "wss://" + networkName + Constants.infuraWsScheme +// guard URL(string: urlString) != nil else {return nil} +// super.init(urlString, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager, +// network: network) +// } +// +// public init?(_ endpoint: String, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil) { +// guard URL(string: endpoint) != nil else {return nil} +// super.init(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager) +// } +// +// public init?(_ endpoint: URL, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil) { +// super.init(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager) +// } +// +// override public class func connectToSocket(_ endpoint: String, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) -> WebsocketProvider? { +// guard let socketProvider = InfuraWebsocketProvider(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager) else {return nil} +// socketProvider.connectSocket() +// return socketProvider +// } +// +// override public class func connectToSocket(_ endpoint: URL, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) -> WebsocketProvider? { +// guard let socketProvider = InfuraWebsocketProvider(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager) else {return nil} +// socketProvider.connectSocket() +// return socketProvider +// } +// +// public static func connectToInfuraSocket(_ network: Networks, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil) -> InfuraWebsocketProvider? { +// guard let socketProvider = InfuraWebsocketProvider(network, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager) else {return nil} +// socketProvider.connectSocket() +// return socketProvider +// } +// +// public func writeMessage(method: InfuraWebsocketMethod, params: [Encodable]) throws { +// let request = JSONRPCRequestFabric.prepareRequest(method, parameters: params) +// let encoder = JSONEncoder() +// let requestData = try encoder.encode(request) +// print(String(decoding: requestData, as: UTF8.self)) +// writeMessage(requestData) +// } +// +// public func setFilterAndGetChanges(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { +// filterTimer?.invalidate() +// filterID = nil +// let params = params ?? [] +// let paramsCount = params.count +// guard method.requiredNumOfParameters == paramsCount || method.requiredNumOfParameters == nil else { +// throw Web3Error.inputError(desc: "Wrong number of params: need - \(method.requiredNumOfParameters!), got - \(paramsCount)") +// } +// try writeMessage(method: method, params: params) +// filterTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(getFilterChanges), userInfo: nil, repeats: true) +// } +// +// public func setFilterAndGetChanges(method: InfuraWebsocketMethod, address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { +// let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) +// try setFilterAndGetChanges(method: method, params: [filterParams]) +// } +// +// public func setFilterAndGetLogs(method: InfuraWebsocketMethod, params: [Encodable]? = nil) throws { +// filterTimer?.invalidate() +// filterID = nil +// let params = params ?? [] +// let paramsCount = params.count +// guard method.requiredNumOfParameters == paramsCount || method.requiredNumOfParameters == nil else { +// throw Web3Error.inputError(desc: "Wrong number of params: need - \(method.requiredNumOfParameters!), got - \(paramsCount)") +// } +// try writeMessage(method: method, params: params) +// filterTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(getFilterLogs), userInfo: nil, repeats: true) +// } +// +// public func setFilterAndGetLogs(method: InfuraWebsocketMethod, address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { +// let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) +// try setFilterAndGetLogs(method: method, params: [filterParams]) +// } +// +// @objc public func getFilterChanges() throws { +// if let id = filterID { +// filterTimer?.invalidate() +// let method = InfuraWebsocketMethod.getFilterChanges +// try writeMessage(method: method, params: [id]) +// } +// } +// +// @objc public func getFilterLogs() throws { +// if let id = filterID { +// filterTimer?.invalidate() +// let method = InfuraWebsocketMethod.getFilterLogs +// try writeMessage(method: method, params: [id]) +// } +// } +// +// public func getFilterLogs(address: EthereumAddress? = nil, fromBlock: BlockNumber? = nil, toBlock: BlockNumber? = nil, topics: [String]? = nil) throws { +// if let id = filterID { +// let filterParams = EventFilterParameters(fromBlock: fromBlock?.stringValue, toBlock: toBlock?.stringValue, topics: [topics], address: [address?.address]) +// let method = InfuraWebsocketMethod.getFilterLogs +// try writeMessage(method: method, params: [id, filterParams]) +// } +// } +// +// public func unistallFilter() throws { +// if let id = filterID { +// filterID = nil +// let method = InfuraWebsocketMethod.uninstallFilter +// try writeMessage(method: method, params: [id]) +// } else { +// throw Web3Error.nodeError(desc: "No filter set") +// } +// } +// +// public func subscribe(params: [Encodable]) throws { +// let method = InfuraWebsocketMethod.subscribe +// try writeMessage(method: method, params: params) +// } +// +// public func unsubscribe(subscriptionID: String) throws { +// let method = InfuraWebsocketMethod.unsubscribe +// subscriptionIDforUnsubscribing = subscriptionID +// try writeMessage(method: method, params: [subscriptionID]) +// } +// +// public func subscribeOnNewHeads() throws { +// let method = InfuraWebsocketMethod.subscribe +// let params = ["newHeads"] +// try writeMessage(method: method, params: params) +// } +// +// public func subscribeOnLogs(addresses: [EthereumAddress]? = nil, topics: [String]? = nil) throws { +// let method = InfuraWebsocketMethod.subscribe +// var stringAddresses = [String]() +// if let addrs = addresses { +// for addr in addrs { +// stringAddresses.append(addr.address) +// } +// } +//// let ts = topics == nil ? nil: [topics!] +// let filterParams = EventFilterParameters(fromBlock: nil, toBlock: nil, topics: [topics], address: stringAddresses) +// try writeMessage(method: method, params: ["logs", filterParams]) +// } +// +// public func subscribeOnNewPendingTransactions() throws { +// let method = InfuraWebsocketMethod.subscribe +// let params = ["newPendingTransactions"] +// try writeMessage(method: method, params: params) +// } +// +// public func subscribeOnSyncing() throws { +// guard network != Networks.Kovan else { +// throw Web3Error.inputError(desc: "Can't sync on Kovan") +// } +// let method = InfuraWebsocketMethod.subscribe +// let params = ["syncing"] +// try writeMessage(method: method, params: params) +// } +// +// /// override WebsocketDelegate +// override public func didReceive(event: WebSocketEvent, client: WebSocket) { +// switch event { +// case .connected(let headers): +// debugMode ? print("websocket is connected, headers:\n \(headers)") : nil +// websocketConnected = true +// delegate.socketConnected(headers) +// case .disconnected(let reason, let code): +// debugMode ? print("websocket is disconnected: \(reason) with code: \(code)") : nil +// websocketConnected = false +// delegate.gotError(error: Web3Error.connectionError) +// case .text(let string): +// debugMode ? print("received text: \(string)") : nil +// websocketDidReceiveMessage(text: string) +// break +// case .binary(let data): +// debugMode ? print("received text: \(String(data: data, encoding: .utf8) ?? "empty")") : nil +// delegate.received(message: data) +// case .ping(_): +// debugMode ? print("ping") : nil +// break +// case .pong(_): +// debugMode ? print("pong") : nil +// break +// case .viabilityChanged(_): +// debugMode ? print("viabilityChanged") : nil +// break +// case .reconnectSuggested(_): +// debugMode ? print("reconnectSuggested") : nil +// break +// case .cancelled: +// debugMode ? print("cancelled") : nil +// websocketConnected = false +// delegate.gotError(error: Web3Error.nodeError(desc: "socket cancelled")) +// case .error(let error): +// debugMode ? print("error: \(String(describing: error))") : nil +// websocketConnected = false +// delegate.gotError(error: error!) +// } +// } +// +// private func websocketDidReceiveMessage(text: String) { +// if let data = text.data(using: String.Encoding.utf8), +// let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { +// if filterID == nil, +// let result = dictionary["result"] as? String { +// // setting filter id +// filterID = result +// } else if let params = dictionary["params"] as? [String: Any], +// let subscription = params["subscription"] as? String, +// let result = params["result"] { +// // subscription result +// subscriptionIDs.insert(subscription) +// delegate.received(message: result) +// } else if let unsubscribed = dictionary["result"] as? Bool { +// // unsubsribe result +// if unsubscribed == true, let id = subscriptionIDforUnsubscribing { +// subscriptionIDs.remove(id) +// } else if let id = subscriptionIDforUnsubscribing { +// delegate.gotError(error: Web3Error.processingError(desc: "Can\'t unsubscribe \(id)")) +// } else { +// delegate.received(message: unsubscribed) +// } +// } else if let message = dictionary["result"] { +// // filter result +// delegate.received(message: message) +// } else { +// delegate.gotError(error: Web3Error.processingError(desc: "Can\'t get known result. Message is: \(text)")) +// } +// } +// } +//} diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index 73093bcde..67e6323ef 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -56,7 +56,7 @@ public enum InfuraWebsocketMethod: String, Encodable { public struct InfuraWebsocketRequest: Encodable { public var jsonrpc: String = "2.0" public var method: InfuraWebsocketMethod? - public var params: [RequestParameter] = [] + public var params: [Encodable] = [] public var id = Counter.increment() enum CodingKeys: String, CodingKey { @@ -70,7 +70,7 @@ public struct InfuraWebsocketRequest: Encodable { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(jsonrpc, forKey: .jsonrpc) try container.encode(method?.rawValue, forKey: .method) - try container.encode(params, forKey: .params) +// try container.encode(params, forKey: .params) try container.encode(id, forKey: .id) } @@ -91,226 +91,226 @@ public protocol Web3SocketDelegate { func gotError(error: Error) } -/// The default websocket provider. -public class WebsocketProvider: Web3Provider, IWebsocketProvider, WebSocketDelegate { - - public func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { - throw Web3Error.inputError(desc: "Sending is unsupported for Websocket provider. Please, use \'sendMessage\'") - } - - public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { - throw Web3Error.inputError(desc: "Sending is unsupported for Websocket provider. Please, use \'sendMessage\'") - } - - public var network: Networks? - public var url: URL - public var session: URLSession = {() -> URLSession in - let config = URLSessionConfiguration.default - let urlSession = URLSession(configuration: config) - return urlSession - }() - public var attachedKeystoreManager: KeystoreManager? = nil - - public var socket: WebSocket - public var delegate: Web3SocketDelegate - /// A flag that is true if socket connected or false if socket doesn't connected. - public var websocketConnected: Bool = false - - private var writeTimer: Timer? = nil - private var messagesStringToWrite: [String] = [] - private var messagesDataToWrite: [Data] = [] - - public init?(_ endpoint: URL, - delegate wsdelegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) { - websocketConnected = false - var endpointString = endpoint.absoluteString - if !(endpointString.hasPrefix("wss://") || endpointString.hasPrefix("ws://")) { - return nil - } - if endpointString.hasPrefix("wss://") && endpointString.hasSuffix(Constants.infuraWsScheme) { - if net == nil { - let networkString = endpointString.replacingOccurrences(of: "wss://", with: "") - .replacingOccurrences(of: Constants.infuraWsScheme, with: "") - switch networkString { - case "mainnet": - network = Networks.Mainnet - case "rinkeby": - network = Networks.Rinkeby - case "ropsten": - network = Networks.Ropsten - case "kovan": - network = Networks.Kovan - default: - break - } - } else { - network = net - } - if network != nil { - endpointString += projectId ?? Constants.infuraToken - } - } - url = URL(string: endpointString)! - delegate = wsdelegate - attachedKeystoreManager = manager - let request = URLRequest(url: url) - socket = WebSocket(request: request) - socket.delegate = self - } - - public init?(_ endpoint: String, - delegate wsdelegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) { - guard URL(string: endpoint) != nil else {return nil} - var finalEndpoint = endpoint - websocketConnected = false - if !(endpoint.hasPrefix("wss://") || endpoint.hasPrefix("ws://")) { - return nil - } - if endpoint.hasPrefix("wss://") && endpoint.hasSuffix(Constants.infuraWsScheme) { - if net == nil { - let networkString = endpoint.replacingOccurrences(of: "wss://", with: "") - .replacingOccurrences(of: Constants.infuraWsScheme, with: "") - switch networkString { - case "mainnet": - network = Networks.Mainnet - case "rinkeby": - network = Networks.Rinkeby - case "ropsten": - network = Networks.Ropsten - case "kovan": - network = Networks.Kovan - default: - break - } - } else { - network = net - } - if network != nil { - finalEndpoint += projectId ?? Constants.infuraToken - } - } - url = URL(string: finalEndpoint)! - delegate = wsdelegate - attachedKeystoreManager = manager - let request = URLRequest(url: url) - socket = WebSocket(request: request) - socket.delegate = self - } - - deinit { - writeTimer?.invalidate() - } - - public func connectSocket() { - writeTimer?.invalidate() - socket.connect() - } - - public func disconnectSocket() { - writeTimer?.invalidate() - socket.disconnect() - } - - public func isConnect() -> Bool { - return websocketConnected - } - - public class func connectToSocket(_ endpoint: String, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) -> WebsocketProvider? { - guard let socketProvider = WebsocketProvider(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager, - network: net) else { - return nil - } - socketProvider.connectSocket() - return socketProvider - } - - public class func connectToSocket(_ endpoint: URL, - delegate: Web3SocketDelegate, - projectId: String? = nil, - keystoreManager manager: KeystoreManager? = nil, - network net: Networks? = nil) -> WebsocketProvider? { - guard let socketProvider = WebsocketProvider(endpoint, - delegate: delegate, - projectId: projectId, - keystoreManager: manager, - network: net) else { - return nil - } - socketProvider.connectSocket() - return socketProvider - } - - public func writeMessage(_ message: T) { - var sMessage: String? = nil - var dMessage: Data? = nil - if !(message.self is String) && !(message.self is Data) { - sMessage = "\(message)" - } else if message.self is String { - sMessage = message as? String - } else if message.self is Data { - dMessage = message as? Data - } - if sMessage != nil { - self.messagesStringToWrite.append(sMessage!) - } else if dMessage != nil { - self.messagesDataToWrite.append(dMessage!) - } - writeTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(performWriteOperations), userInfo: nil, repeats: true) - } - - @objc private func performWriteOperations() { - if websocketConnected { - writeTimer?.invalidate() - for s in messagesStringToWrite { - socket.write(string: s) - } - for d in messagesDataToWrite { - socket.write(data: d) - } - } - } - - public func didReceive(event: WebSocketEvent, client: WebSocket) { - switch event { - case .connected(let headers): - websocketConnected = true - delegate.socketConnected(headers) - case .disconnected(let reason, let code): - print("socket disconnected: \(reason) , code: \(code)") - websocketConnected = false - delegate.gotError(error: Web3Error.connectionError) - case .text(let string): - delegate.received(message: string) - break - case .binary(let data): - delegate.received(message: data) - case .ping(_): - break - case .pong(_): - break - case .viabilityChanged(_): - break - case .reconnectSuggested(_): - break - case .cancelled: - websocketConnected = false - delegate.gotError(error: Web3Error.nodeError(desc: "socket cancelled")) - case .error(let error): - websocketConnected = false - delegate.gotError(error: error!) - } - } -} +///// The default websocket provider. +//public class WebsocketProvider: Web3Provider, IWebsocketProvider, WebSocketDelegate { +// +// public func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { +// throw Web3Error.inputError(desc: "Sending is unsupported for Websocket provider. Please, use \'sendMessage\'") +// } +// +// public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { +// throw Web3Error.inputError(desc: "Sending is unsupported for Websocket provider. Please, use \'sendMessage\'") +// } +// +// public var network: Networks? +// public var url: URL +// public var session: URLSession = {() -> URLSession in +// let config = URLSessionConfiguration.default +// let urlSession = URLSession(configuration: config) +// return urlSession +// }() +// public var attachedKeystoreManager: KeystoreManager? = nil +// +// public var socket: WebSocket +// public var delegate: Web3SocketDelegate +// /// A flag that is true if socket connected or false if socket doesn't connected. +// public var websocketConnected: Bool = false +// +// private var writeTimer: Timer? = nil +// private var messagesStringToWrite: [String] = [] +// private var messagesDataToWrite: [Data] = [] +// +// public init?(_ endpoint: URL, +// delegate wsdelegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) { +// websocketConnected = false +// var endpointString = endpoint.absoluteString +// if !(endpointString.hasPrefix("wss://") || endpointString.hasPrefix("ws://")) { +// return nil +// } +// if endpointString.hasPrefix("wss://") && endpointString.hasSuffix(Constants.infuraWsScheme) { +// if net == nil { +// let networkString = endpointString.replacingOccurrences(of: "wss://", with: "") +// .replacingOccurrences(of: Constants.infuraWsScheme, with: "") +// switch networkString { +// case "mainnet": +// network = Networks.Mainnet +// case "rinkeby": +// network = Networks.Rinkeby +// case "ropsten": +// network = Networks.Ropsten +// case "kovan": +// network = Networks.Kovan +// default: +// break +// } +// } else { +// network = net +// } +// if network != nil { +// endpointString += projectId ?? Constants.infuraToken +// } +// } +// url = URL(string: endpointString)! +// delegate = wsdelegate +// attachedKeystoreManager = manager +// let request = URLRequest(url: url) +// socket = WebSocket(request: request) +// socket.delegate = self +// } +// +// public init?(_ endpoint: String, +// delegate wsdelegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) { +// guard URL(string: endpoint) != nil else {return nil} +// var finalEndpoint = endpoint +// websocketConnected = false +// if !(endpoint.hasPrefix("wss://") || endpoint.hasPrefix("ws://")) { +// return nil +// } +// if endpoint.hasPrefix("wss://") && endpoint.hasSuffix(Constants.infuraWsScheme) { +// if net == nil { +// let networkString = endpoint.replacingOccurrences(of: "wss://", with: "") +// .replacingOccurrences(of: Constants.infuraWsScheme, with: "") +// switch networkString { +// case "mainnet": +// network = Networks.Mainnet +// case "rinkeby": +// network = Networks.Rinkeby +// case "ropsten": +// network = Networks.Ropsten +// case "kovan": +// network = Networks.Kovan +// default: +// break +// } +// } else { +// network = net +// } +// if network != nil { +// finalEndpoint += projectId ?? Constants.infuraToken +// } +// } +// url = URL(string: finalEndpoint)! +// delegate = wsdelegate +// attachedKeystoreManager = manager +// let request = URLRequest(url: url) +// socket = WebSocket(request: request) +// socket.delegate = self +// } +// +// deinit { +// writeTimer?.invalidate() +// } +// +// public func connectSocket() { +// writeTimer?.invalidate() +// socket.connect() +// } +// +// public func disconnectSocket() { +// writeTimer?.invalidate() +// socket.disconnect() +// } +// +// public func isConnect() -> Bool { +// return websocketConnected +// } +// +// public class func connectToSocket(_ endpoint: String, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) -> WebsocketProvider? { +// guard let socketProvider = WebsocketProvider(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager, +// network: net) else { +// return nil +// } +// socketProvider.connectSocket() +// return socketProvider +// } +// +// public class func connectToSocket(_ endpoint: URL, +// delegate: Web3SocketDelegate, +// projectId: String? = nil, +// keystoreManager manager: KeystoreManager? = nil, +// network net: Networks? = nil) -> WebsocketProvider? { +// guard let socketProvider = WebsocketProvider(endpoint, +// delegate: delegate, +// projectId: projectId, +// keystoreManager: manager, +// network: net) else { +// return nil +// } +// socketProvider.connectSocket() +// return socketProvider +// } +// +// public func writeMessage(_ message: T) { +// var sMessage: String? = nil +// var dMessage: Data? = nil +// if !(message.self is String) && !(message.self is Data) { +// sMessage = "\(message)" +// } else if message.self is String { +// sMessage = message as? String +// } else if message.self is Data { +// dMessage = message as? Data +// } +// if sMessage != nil { +// self.messagesStringToWrite.append(sMessage!) +// } else if dMessage != nil { +// self.messagesDataToWrite.append(dMessage!) +// } +// writeTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(performWriteOperations), userInfo: nil, repeats: true) +// } +// +// @objc private func performWriteOperations() { +// if websocketConnected { +// writeTimer?.invalidate() +// for s in messagesStringToWrite { +// socket.write(string: s) +// } +// for d in messagesDataToWrite { +// socket.write(data: d) +// } +// } +// } +// +// public func didReceive(event: WebSocketEvent, client: WebSocket) { +// switch event { +// case .connected(let headers): +// websocketConnected = true +// delegate.socketConnected(headers) +// case .disconnected(let reason, let code): +// print("socket disconnected: \(reason) , code: \(code)") +// websocketConnected = false +// delegate.gotError(error: Web3Error.connectionError) +// case .text(let string): +// delegate.received(message: string) +// break +// case .binary(let data): +// delegate.received(message: data) +// case .ping(_): +// break +// case .pong(_): +// break +// case .viabilityChanged(_): +// break +// case .reconnectSuggested(_): +// break +// case .cancelled: +// websocketConnected = false +// delegate.gotError(error: Web3Error.nodeError(desc: "socket cancelled")) +// case .error(let error): +// websocketConnected = false +// delegate.gotError(error: error!) +// } +// } +//} From 0bc450baea54d110b221702872d064bb200cc954 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 18:18:02 +0700 Subject: [PATCH 34/45] Delete old HTTP(S) network code. --- Sources/web3swift/Web3/Web3+Instance.swift | 6 - Sources/web3swift/Web3/Web3+JSONRPC.swift | 231 --------------------- Sources/web3swift/Web3/Web3+Methods.swift | 92 -------- 3 files changed, 329 deletions(-) delete mode 100755 Sources/web3swift/Web3/Web3+Methods.swift diff --git a/Sources/web3swift/Web3/Web3+Instance.swift b/Sources/web3swift/Web3/Web3+Instance.swift index eb94ea5ee..6ae0ca51e 100755 --- a/Sources/web3swift/Web3/Web3+Instance.swift +++ b/Sources/web3swift/Web3/Web3+Instance.swift @@ -12,12 +12,6 @@ import BigInt public class web3 { public var provider: Web3Provider public var transactionOptions: TransactionOptions = TransactionOptions.defaultOptions - public var defaultBlock = "latest" - - /// Add a provider request to the dispatch queue. - public func dispatch(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { - try await provider.sendAsync(request) - } /// Raw initializer using a Web3Provider protocol object, dispatch queue and request dispatcher. public init(provider prov: Web3Provider) { diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/web3swift/Web3/Web3+JSONRPC.swift index a16a30450..717b89cc4 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/web3swift/Web3/Web3+JSONRPC.swift @@ -23,237 +23,6 @@ public struct Counter { } } -/// JSON RPC request structure for serialization and deserialization purposes. -//public struct JSONRPCrequest: Encodable { -public struct JSONRPCrequest: Encodable { - public var jsonrpc: String = "2.0" - public var method: JSONRPCmethod? - public var params: [RequestParameter] = [] - public var id: UInt = Counter.increment() - - enum CodingKeys: String, CodingKey { - case jsonrpc - case method - case params - case id - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(jsonrpc, forKey: .jsonrpc) - try container.encode(method?.rawValue, forKey: .method) - try container.encode(params, forKey: .params) - try container.encode(id, forKey: .id) - } - - public var isValid: Bool { - get { - if self.method == nil { - return false - } - guard let method = self.method else {return false} - return method.requiredNumOfParameters == self.params.count - } - } -} - -/// JSON RPC batch request structure for serialization and deserialization purposes. -public struct JSONRPCrequestBatch: Encodable { - var requests: [JSONRPCrequest] - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self.requests) - } -} - -/// JSON RPC response structure for serialization and deserialization purposes. -public struct JSONRPCresponse: Decodable{ - public var id: Int - public var jsonrpc = "2.0" - public var result: Any? - public var error: ErrorMessage? - public var message: String? - - enum JSONRPCresponseKeys: String, CodingKey { - case id = "id" - case jsonrpc = "jsonrpc" - case result = "result" - case error = "error" - } - - public init(id: Int, jsonrpc: String, result: Any?, error: ErrorMessage?) { - self.id = id - self.jsonrpc = jsonrpc - self.result = result - self.error = error - } - - public struct ErrorMessage: Decodable { - public var code: Int - public var message: String - } - - internal var decodableTypes: [Decodable.Type] = [ - [EventLog].self, - [TransactionDetails].self, - [TransactionReceipt].self, - [Block].self, - [String].self, - [Int].self, - [Bool].self, - EventLog.self, - TransactionDetails.self, - TransactionReceipt.self, - Block.self, - String.self, - Int.self, - Bool.self, - [String: String].self, - [String: Int].self, - [String: [String: [String: [String]]]].self, - Web3.Oracle.FeeHistory.self - ] - - // FIXME: Make me a real generic - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: JSONRPCresponseKeys.self) - let id: Int = try container.decode(Int.self, forKey: .id) - let jsonrpc: String = try container.decode(String.self, forKey: .jsonrpc) - let errorMessage = try container.decodeIfPresent(ErrorMessage.self, forKey: .error) - if errorMessage != nil { - self.init(id: id, jsonrpc: jsonrpc, result: nil, error: errorMessage) - return - } - // TODO: make me generic (DecodableFromHex or Decodable) - /// This is all available types of `result` to init - /// Now its type is `Any?`, since you're typecasting this any to exact each response, - /// coz you're knowing response to what request it would be, - /// and you're could be sure about API Response structure. - /// - /// So since we're typecasting this explicitly each tyme, `result` property could be set - /// to protocol type like `Decodable` or `DevodableFromHex` or something, - /// and this code could be reduced so hard. - var result: Any? = nil - if let rawValue = try? container.decodeIfPresent(String.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(Int.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(Bool.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(EventLog.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(Block.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(TransactionReceipt.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(TransactionDetails.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([EventLog].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([Block].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([TransactionReceipt].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([TransactionDetails].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(TxPoolStatus.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(TxPoolContent.self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([Bool].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([Int].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([String].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([String: String].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([String: Int].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([String: [String: [String: String]]].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent([String: [String: [String: [String: String?]]]].self, forKey: .result) { - result = rawValue - } else if let rawValue = try? container.decodeIfPresent(Web3.Oracle.FeeHistory.self, forKey: .result) { - result = rawValue - } - self.init(id: id, jsonrpc: jsonrpc, result: result, error: nil) - } - - // FIXME: Make me a real generic - // MARK: - This fits for DecodableFromHex - /// Get the JSON RCP reponse value by deserializing it into some native class. - /// - /// Returns nil if serialization fails - public func getValue() -> T? { - let type = T.self - - if type == BigUInt.self { - guard let string = self.result as? String else {return nil} - guard let value = BigUInt(string.stripHexPrefix(), radix: 16) else {return nil} - return value as? T - } else if type == BigInt.self { - guard let string = self.result as? String else {return nil} - guard let value = BigInt(string.stripHexPrefix(), radix: 16) else {return nil} - return value as? T - } else if type == Data.self { - guard let string = self.result as? String else {return nil} - guard let value = Data.fromHex(string) else {return nil} - return value as? T - } else if type == EthereumAddress.self { - guard let string = self.result as? String else {return nil} - guard let value = EthereumAddress(string, ignoreChecksum: true) else {return nil} - return value as? T - } -// else if slf == String.self { -// guard let value = self.result as? T else {return nil} -// return value -// } else if slf == Int.self { -// guard let value = self.result as? T else {return nil} -// return value -// } - else if type == [BigUInt].self { - guard let string = self.result as? [String] else {return nil} - let values = string.compactMap { (str) -> BigUInt? in - return BigUInt(str.stripHexPrefix(), radix: 16) - } - return values as? T - } else if type == [BigInt].self { - guard let string = self.result as? [String] else {return nil} - let values = string.compactMap { (str) -> BigInt? in - return BigInt(str.stripHexPrefix(), radix: 16) - } - return values as? T - } else if type == [Data].self { - guard let string = self.result as? [String] else {return nil} - let values = string.compactMap { (str) -> Data? in - return Data.fromHex(str) - } - return values as? T - } else if type == [EthereumAddress].self { - guard let string = self.result as? [String] else {return nil} - let values = string.compactMap { (str) -> EthereumAddress? in - return EthereumAddress(str, ignoreChecksum: true) - } - return values as? T - } - guard let value = self.result as? T else {return nil} - return value - } -} - -/// JSON RPC batch response structure for serialization and deserialization purposes. -public struct JSONRPCresponseBatch: Decodable { - var responses: [JSONRPCresponse] - - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let responses = try container.decode([JSONRPCresponse].self) - self.responses = responses - } -} - /// Transaction parameters JSON structure for interaction with Ethereum node. public struct TransactionParameters: Codable { /// accessList parameter JSON structure diff --git a/Sources/web3swift/Web3/Web3+Methods.swift b/Sources/web3swift/Web3/Web3+Methods.swift deleted file mode 100755 index 51b5cfe98..000000000 --- a/Sources/web3swift/Web3/Web3+Methods.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// Web3+APIMethod.swift -// Web3swift -// -// Created by Yaroslav on 24.05.2022. -// - -import Foundation -import BigInt - -public enum JSONRPCmethod: String, Encodable { - // 0 parameter in call - case gasPrice = "eth_gasPrice" - case blockNumber = "eth_blockNumber" - case getNetwork = "net_version" - case getAccounts = "eth_accounts" - case getTxPoolStatus = "txpool_status" - case getTxPoolContent = "txpool_content" - case getTxPoolInspect = "txpool_inspect" - - // 1 parameter in call - case sendRawTransaction = "eth_sendRawTransaction" - case sendTransaction = "eth_sendTransaction" - case getTransactionByHash = "eth_getTransactionByHash" - case getTransactionReceipt = "eth_getTransactionReceipt" - case personalSign = "eth_sign" - case unlockAccount = "personal_unlockAccount" - case createAccount = "personal_createAccount" - case getLogs = "eth_getLogs" - - // 2 parameters in call - case call = "eth_call" - case estimateGas = "eth_estimateGas" - case getTransactionCount = "eth_getTransactionCount" - case getBalance = "eth_getBalance" - case getStorageAt = "eth_getStorageAt" - case getCode = "eth_getCode" - case getBlockByHash = "eth_getBlockByHash" - case getBlockByNumber = "eth_getBlockByNumber" - - // 3 parameters in call - case feeHistory = "eth_feeHistory" - - public var requiredNumOfParameters: Int { - switch self { - case .gasPrice, - .blockNumber, - .getNetwork, - .getAccounts, - .getTxPoolStatus, - .getTxPoolContent, - .getTxPoolInspect: - return 0 - case .sendRawTransaction, - .sendTransaction, - .getTransactionByHash, - .getTransactionReceipt, - .personalSign, - .unlockAccount, - .createAccount, - .getLogs, - .estimateGas: - return 1 - case .call, - .getTransactionCount, - .getBalance, - .getStorageAt, - .getCode, - .getBlockByHash, - .getBlockByNumber: - return 2 - case .feeHistory: - return 3 - } - } -} - -public struct JSONRPCRequestFabric { - public static func prepareRequest(_ method: JSONRPCmethod, parameters: [APIRequestParameterType]) -> JSONRPCrequest { - var request = JSONRPCrequest() - request.method = method - request.params = parameters.compactMap { RequestParameter.init(rawValue: $0) } - return request - } - - public static func prepareRequest(_ method: InfuraWebsocketMethod, parameters: [APIRequestParameterType]) -> InfuraWebsocketRequest { - var request = InfuraWebsocketRequest() - request.method = method - request.params = parameters.compactMap { RequestParameter.init(rawValue: $0) } - return request - } -} From 983d084de44072818f19f825e1d298ab4a97f87d Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 18:18:58 +0700 Subject: [PATCH 35/45] Temporary comment out not failed to build tests. --- .../localTests/web3swiftTests.swift | 12 ++--- .../remoteTests/InfuraTests.swift | 2 +- .../remoteTests/WebsocketTests.swift | 48 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Tests/web3swiftTests/localTests/web3swiftTests.swift b/Tests/web3swiftTests/localTests/web3swiftTests.swift index cb8c218ae..131bf98d5 100755 --- a/Tests/web3swiftTests/localTests/web3swiftTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftTests.swift @@ -103,12 +103,12 @@ class web3swiftTests: XCTestCase { XCTAssert(ibn == "XE83FUTTUNPK7WZJSGGCWVEBARQWQ8YML4") } - func testGenericRPCresponse() throws { - let hex = "0x1" - let rpcResponse = JSONRPCresponse(id: 1, jsonrpc: "2.0", result: hex, error: nil) - let value: BigUInt? = rpcResponse.getValue() - XCTAssert(value == 1) - } +// func testGenericRPCresponse() throws { +// let hex = "0x1" +// let rpcResponse = JSONRPCresponse(id: 1, jsonrpc: "2.0", result: hex, error: nil) +// let value: BigUInt? = rpcResponse.getValue() +// XCTAssert(value == 1) +// } func testPublicMappingsAccess() async throws { let jsonString = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"users\",\"outputs\":[{\"name\":\"name\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"userDeviceCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalUsers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]" diff --git a/Tests/web3swiftTests/remoteTests/InfuraTests.swift b/Tests/web3swiftTests/remoteTests/InfuraTests.swift index dae46a96b..e2c7c5cca 100755 --- a/Tests/web3swiftTests/remoteTests/InfuraTests.swift +++ b/Tests/web3swiftTests/remoteTests/InfuraTests.swift @@ -76,7 +76,7 @@ class InfuraTests: XCTestCase { filter.toBlock = .blockNumber(UInt(5200120)) filter.addresses = [EthereumAddress("0x53066cddbc0099eb6c96785d9b3df2aaeede5da3")!] filter.parameterFilters = [([EthereumAddress("0xefdcf2c36f3756ce7247628afdb632fa4ee12ec5")!] as [EventFilterable]), (nil as [EventFilterable]?)] - let eventParserResult = try await contract!.getIndexedEventsPromise(eventName: "Transfer", filter: filter, joinWithReceipts: true) + let eventParserResult = try await contract!.getIndexedEvents(eventName: "Transfer", filter: filter, joinWithReceipts: true) print(eventParserResult) XCTAssert(eventParserResult.count == 2) XCTAssert(eventParserResult.first?.transactionReceipt != nil) diff --git a/Tests/web3swiftTests/remoteTests/WebsocketTests.swift b/Tests/web3swiftTests/remoteTests/WebsocketTests.swift index bedf6394c..91b7a13b6 100644 --- a/Tests/web3swiftTests/remoteTests/WebsocketTests.swift +++ b/Tests/web3swiftTests/remoteTests/WebsocketTests.swift @@ -59,7 +59,7 @@ class SpyDelegate: Web3SocketDelegate { class WebsocketTests: XCTestCase { let spyDelegate = SpyDelegate() - var socketProvider: InfuraWebsocketProvider? +// var socketProvider: InfuraWebsocketProvider? // FIXME: Failed on async/await // func testSocketConnection(){ @@ -159,27 +159,27 @@ class WebsocketTests: XCTestCase { // } // } - func testFilter() { - guard let socketProvider = InfuraWebsocketProvider.connectToInfuraSocket(.Mainnet, delegate: spyDelegate) else { - return XCTFail() - } - self.socketProvider = socketProvider - spyDelegate.asyncExpectation = expectation(description: "Delegate called") - try! self.socketProvider?.setFilterAndGetLogs(method: .newFilter, address: EthereumAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")!, fromBlock: .earliest, toBlock: .latest, topics: nil) - // DispatchQueue.main.asyncAfter(deadline: .now()+5) { [unowned self] in - // try! self.socketProvider!.subscribeOnNewPendingTransactions() - // } - waitForExpectations(timeout: 1000) { error in - if let error = error { - XCTFail("waitForExpectationsWithTimeout errored: \(error)") - } - - guard self.spyDelegate.somethingWithDelegateResult != nil else { - XCTFail("Expected delegate to be called") - return - } - - XCTAssert(true) - } - } +// func testFilter() { +// guard let socketProvider = InfuraWebsocketProvider.connectToInfuraSocket(.Mainnet, delegate: spyDelegate) else { +// return XCTFail() +// } +// self.socketProvider = socketProvider +// spyDelegate.asyncExpectation = expectation(description: "Delegate called") +// try! self.socketProvider?.setFilterAndGetLogs(method: .newFilter, address: EthereumAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")!, fromBlock: .earliest, toBlock: .latest, topics: nil) +// // DispatchQueue.main.asyncAfter(deadline: .now()+5) { [unowned self] in +// // try! self.socketProvider!.subscribeOnNewPendingTransactions() +// // } +// waitForExpectations(timeout: 1000) { error in +// if let error = error { +// XCTFail("waitForExpectationsWithTimeout errored: \(error)") +// } +// +// guard self.spyDelegate.somethingWithDelegateResult != nil else { +// XCTFail("Expected delegate to be called") +// return +// } +// +// XCTAssert(true) +// } +// } } From bbe64ef2c70d18ca3dd5b6ca58c5408076e385d1 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 18:19:56 +0700 Subject: [PATCH 36/45] Comment out some duplicating code. --- Sources/web3swift/Web3/Web3+Eth.swift | 67 ++++++++---------------- Sources/web3swift/Web3/Web3+TxPool.swift | 8 +-- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/Sources/web3swift/Web3/Web3+Eth.swift b/Sources/web3swift/Web3/Web3+Eth.swift index d485de6ab..c4f24e761 100755 --- a/Sources/web3swift/Web3/Web3+Eth.swift +++ b/Sources/web3swift/Web3/Web3+Eth.swift @@ -7,8 +7,8 @@ import Foundation import BigInt +// FIXME: None of the follow methods are syncronious. extension web3.Eth { - /// Send an EthereumTransaction object to the network. Transaction is either signed locally if there is a KeystoreManager /// object bound to the web3 instance, or sent unsigned to the node. For local signing the password is required. /// @@ -34,10 +34,10 @@ extension web3.Eth { /// This function is synchronous! /// /// Returns the Result object that indicates either success of failure. - func call(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions) async throws -> Data { - let result = try await self.callTransaction(transaction, transactionOptions: transactionOptions) - return result - } +// func call(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions) async throws -> Data { +// let result = try await self.callTransaction(transaction, transactionOptions: transactionOptions) +// return result +// } /// Send raw Ethereum transaction data to the network. /// @@ -59,18 +59,18 @@ extension web3.Eth { return result } - /// Returns a total number of transactions sent by the particular Ethereum address. - /// - /// "onBlock" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") - /// or the expected state after all the transactions in memory pool are applied ("pending"). - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getTransactionCount(address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { - let result = try await self.getTransactionCount(for: address, onBlock: onBlock) - return result - } +// /// Returns a total number of transactions sent by the particular Ethereum address. +// /// +// /// "onBlock" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") +// /// or the expected state after all the transactions in memory pool are applied ("pending"). +// /// +// /// This function is synchronous! +// /// +// /// Returns the Result object that indicates either success of failure. +// public func getTransactionCount(address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { +// let result = try await self.getTransactionCount(for: address, onBlock: onBlock) +// return result +// } /// Returns a balance of particular Ethereum address in Wei units (1 ETH = 10^18 Wei). /// @@ -80,7 +80,7 @@ extension web3.Eth { /// This function is synchronous! /// /// Returns the Result object that indicates either success of failure. - public func getBalance(address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { + public func getBalance(address: EthereumAddress, onBlock: BlockNumber) async throws -> BigUInt { let result = try await self.getBalance(for: address, onBlock: onBlock) return result } @@ -185,7 +185,7 @@ extension web3.Eth { /// /// Returns the Result object that indicates either success of failure. public func getBlockByHash(_ hash: String, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.block(for: hash, fullTransactions: fullTransactions) + let result = try await self.block(by: hash, fullTransactions: fullTransactions) return result } @@ -197,19 +197,7 @@ extension web3.Eth { /// /// Returns the Result object that indicates either success of failure. public func getBlockByHash(_ hash: Data, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.block(for: hash, fullTransactions: fullTransactions) - return result - } - - /// Get information about the particular block in Ethereum network. If "fullTransactions" parameter is set to "true" - /// this call fill do a virtual join and fetch not just transaction hashes from this block, - /// but full decoded EthereumTransaction objects. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBlockByNumber(_ number: UInt, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.blockBy(number: number, fullTransactions: fullTransactions) + let result = try await self.block(by: hash, fullTransactions: fullTransactions) return result } @@ -220,22 +208,11 @@ extension web3.Eth { /// This function is synchronous! /// /// Returns the Result object that indicates either success of failure. - public func getBlockByNumber(_ number: BigUInt, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.blockBy(number: number, fullTransactions: fullTransactions) + public func getBlockByNumber(_ number: BlockNumber, fullTransactions: Bool = false) async throws -> Block { + let result = try await self.block(by: number, fullTransactions: fullTransactions) return result } - /// Get information about the particular block in Ethereum network. If "fullTransactions" parameter is set to "true" - /// this call fill do a virtual join and fetch not just transaction hashes from this block, - /// but full decoded EthereumTransaction objects. - /// - /// This function is synchronous! - /// - /// - public func getBlockByNumber(_ block: String, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.blockBy(number: block, fullTransactions: fullTransactions) - return result - } /** Convenience wrapper to send Ethereum to another address. Internally it creates a virtual contract and encodes all the options and data. diff --git a/Sources/web3swift/Web3/Web3+TxPool.swift b/Sources/web3swift/Web3/Web3+TxPool.swift index ab0cf028d..b4d598650 100755 --- a/Sources/web3swift/Web3/Web3+TxPool.swift +++ b/Sources/web3swift/Web3/Web3+TxPool.swift @@ -8,10 +8,10 @@ import Foundation import BigInt extension web3.TxPool { - public func getInspect() async throws -> [String: [String: [String: String]]] { - let result = try await self.txPoolInspect() - return result - } +// public func getInspect() async throws -> [String: [String: [String: String]]] { +// let result = try await self.txPoolInspect() +// return result +// } public func getStatus() async throws -> TxPoolStatus { let result = try await self.txPoolStatus() From 16d6f1c95a6fa43954563cb023b166815a8aefcb Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 19:02:29 +0700 Subject: [PATCH 37/45] Delete `Web3+Eth.swift` since its purpose were to make Promise methods synchronous, but after switching all concurrency to async/await all of that method becomes redundant and more than that it becomes async. --- Sources/web3swift/Web3/Web3+Eth.swift | 332 -------------------------- 1 file changed, 332 deletions(-) delete mode 100755 Sources/web3swift/Web3/Web3+Eth.swift diff --git a/Sources/web3swift/Web3/Web3+Eth.swift b/Sources/web3swift/Web3/Web3+Eth.swift deleted file mode 100755 index c4f24e761..000000000 --- a/Sources/web3swift/Web3/Web3+Eth.swift +++ /dev/null @@ -1,332 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - -// FIXME: None of the follow methods are syncronious. -extension web3.Eth { - /// Send an EthereumTransaction object to the network. Transaction is either signed locally if there is a KeystoreManager - /// object bound to the web3 instance, or sent unsigned to the node. For local signing the password is required. - /// - /// "options" object can override the "to", "gasPrice", "gasLimit" and "value" parameters is pre-formed transaction. - /// "from" field in "options" is mandatory for both local and remote signing. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func sendTransaction(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions, password: String = "web3swift") async throws -> TransactionSendingResult { - let result = try await self.send(transaction, transactionOptions: transactionOptions, password: password) - return result - } - - /// Performs a non-mutating "call" to some smart-contract. EthereumTransaction bears all function parameters required for the call. - /// Does NOT decode the data returned from the smart-contract. - /// "options" object can override the "to", "gasPrice", "gasLimit" and "value" parameters is pre-formed transaction. - /// "from" field in "options" is mandatory for both local and remote signing. - /// - /// "onString" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") - /// or the expected state after all the transactions in memory pool are applied ("pending"). - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. -// func call(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions) async throws -> Data { -// let result = try await self.callTransaction(transaction, transactionOptions: transactionOptions) -// return result -// } - - /// Send raw Ethereum transaction data to the network. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func sendRawTransaction(_ transaction: Data) async throws -> TransactionSendingResult { - let result = try await self.send(raw: transaction) - return result - } - - /// Send raw Ethereum transaction data to the network by first serializing the EthereumTransaction object. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func sendRawTransaction(_ transaction: EthereumTransaction) async throws -> TransactionSendingResult { - let result = try await self.send(raw: transaction) - return result - } - -// /// Returns a total number of transactions sent by the particular Ethereum address. -// /// -// /// "onBlock" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") -// /// or the expected state after all the transactions in memory pool are applied ("pending"). -// /// -// /// This function is synchronous! -// /// -// /// Returns the Result object that indicates either success of failure. -// public func getTransactionCount(address: EthereumAddress, onBlock: String = "latest") async throws -> BigUInt { -// let result = try await self.getTransactionCount(for: address, onBlock: onBlock) -// return result -// } - - /// Returns a balance of particular Ethereum address in Wei units (1 ETH = 10^18 Wei). - /// - /// "onString" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") - /// or the expected state after all the transactions in memory pool are applied ("pending"). - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBalance(address: EthereumAddress, onBlock: BlockNumber) async throws -> BigUInt { - let result = try await self.getBalance(for: address, onBlock: onBlock) - return result - } - - /// Returns a block number of the last mined block that Ethereum node knows about. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBlockNumber() async throws -> BigUInt { - let result = try await self.blockNumber() - return result - } - - /// Returns a current gas price in the units of Wei. The node has internal algorithms for averaging over the last few blocks. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getGasPrice() async throws -> BigUInt { - let result = try await self.gasPrice() - return result - } - - /// Returns transaction details for particular transaction hash. Details indicate position of the transaction in a particular block, - /// as well as original transaction details such as value, gas limit, gas price, etc. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getTransactionDetails(_ txhash: Data) async throws -> TransactionDetails { - let result = try await self.transactionDetails(txhash) - return result - } - - /// Returns transaction details for particular transaction hash. Details indicate position of the transaction in a particular block, - /// as well as original transaction details such as value, gas limit, gas price, etc. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getTransactionDetails(_ txhash: String) async throws -> TransactionDetails { - let result = try await self.transactionDetails(txhash) - return result - } - - /// Returns transaction receipt for particular transaction hash. Receipt indicate what has happened when the transaction - /// was included in block, so it contains logs and status, such as succesful or failed transaction. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getTransactionReceipt(_ txhash: Data) async throws -> TransactionReceipt { - let result = try await self.transactionReceipt(txhash) - return result - } - - /// Returns transaction receipt for particular transaction hash. Receipt indicate what has happened when the transaction - /// was included in block, so it contains logs and status, such as succesful or failed transaction. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getTransactionReceipt(_ txhash: String) async throws -> TransactionReceipt { - let result = try await self.transactionReceipt(txhash) - return result - } - - /// Estimates a minimal amount of gas required to run a transaction. To do it the Ethereum node tries to run it and counts - /// how much gas it consumes for computations. Setting the transaction gas limit lower than the estimate will most likely - /// result in a failing transaction. - /// - /// "onString" field determines if value is returned based on the state of a blockchain on the latest mined block ("latest") - /// or the expected state after all the transactions in memory pool are applied ("pending"). - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - /// Error can also indicate that transaction is invalid in the current state, so formally it's gas limit is infinite. - /// An example of such transaction can be sending an amount of ETH that is larger than the current account balance. - public func estimateGas(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions?) async throws -> BigUInt { - let result = try await self.estimateGas(for: transaction, transactionOptions: transactionOptions) - return result - } - - /// Get a list of Ethereum accounts that a node knows about. - /// If one has attached a Keystore Manager to the web3 object it returns accounts known to the keystore. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getAccounts() async throws -> [EthereumAddress] { - let result = try await self.ownedAccounts() - return result - } - - /// Get information about the particular block in Ethereum network. If "fullTransactions" parameter is set to "true" - /// this call fill do a virtual join and fetch not just transaction hashes from this block, - /// but full decoded EthereumTransaction objects. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBlockByHash(_ hash: String, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.block(by: hash, fullTransactions: fullTransactions) - return result - } - - /// Get information about the particular block in Ethereum network. If "fullTransactions" parameter is set to "true" - /// this call fill do a virtual join and fetch not just transaction hashes from this block, - /// but full decoded EthereumTransaction objects. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBlockByHash(_ hash: Data, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.block(by: hash, fullTransactions: fullTransactions) - return result - } - - /// Get information about the particular block in Ethereum network. If "fullTransactions" parameter is set to "true" - /// this call fill do a virtual join and fetch not just transaction hashes from this block, - /// but full decoded EthereumTransaction objects. - /// - /// This function is synchronous! - /// - /// Returns the Result object that indicates either success of failure. - public func getBlockByNumber(_ number: BlockNumber, fullTransactions: Bool = false) async throws -> Block { - let result = try await self.block(by: number, fullTransactions: fullTransactions) - return result - } - - - /** - Convenience wrapper to send Ethereum to another address. Internally it creates a virtual contract and encodes all the options and data. - - Parameters: - - to: EthereumAddress to send funds to - - amount: BigUInt indicating the amount in wei - - extraData: Additional data to attach to the transaction - - options: Web3Options to override the default gas price, gas limit. "Value" field of the options is ignored and the "amount" parameter is used instead - - - returns: - - TransactionIntermediate object - - */ - public func sendETH(to: EthereumAddress, amount: BigUInt, extraData: Data = Data(), transactionOptions: TransactionOptions? = nil) -> WriteTransaction? { - let contract = self.web3.contract(Web3.Utils.coldWalletABI, at: to, abiVersion: 2) - var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) - mergedOptions.value = amount - let writeTX = contract?.write("fallback", extraData: extraData, transactionOptions: mergedOptions) - return writeTX - } - - /** - *Convenience wrapper to send Ethereum to another address. Internally it creates a virtual contract and encodes all the options and data.* - - - parameters: - - to: EthereumAddress to send funds to - - amount: String in "units" demonimation. It can contain either "," or "." decimal separator. - - units: Ethereum units indicating the denomination of amout about - - extraData: Additional data to attach to the transaction - - options: Web3Options to override the default gas price, gas limit. "Value" field of the options is ignored and the "amount" parameter is used instead - - - returns: - - TransactionIntermediate object - - * String "1.01" and units: .eth will result in sending 1.01 ETH to another address* - */ - public func sendETH(to: EthereumAddress, amount: String, units: Web3.Utils.Units = .eth, extraData: Data = Data(), transactionOptions: TransactionOptions? = nil) -> WriteTransaction? { - guard let value = Web3.Utils.parseToBigUInt(amount, units: .eth) else {return nil} - return sendETH(to: to, amount: value, extraData: extraData, transactionOptions: transactionOptions) - } - - /** - *Convenience wrapper to send Ethereum to another address. Internally it creates a virtual contract and encodes all the options and data.* - - - parameters: - - from: EthereumAddress to send funds from - - to: EthereumAddress to send funds to - - amount: String in "units" demonimation. It can contain either "," or "." decimal separator. - - units: Ethereum units indicating the denomination of amout about - - extraData: Additional data to attach to the transaction - - options: Web3Options to override the default gas price, gas limit. "Value" field of the options is ignored and the "amount" parameter is used instead. "From" parameter is also ignored. - - - returns: - - TransactionIntermediate object - - * String "1.01" and units: .eth will result in sending 1.01 ETH to another address* - */ - public func sendETH(from: EthereumAddress, to: EthereumAddress, amount: String, units: Web3.Utils.Units = .eth, extraData: Data = Data(), transactionOptions: TransactionOptions? = nil) -> WriteTransaction? { - guard let value = Web3.Utils.parseToBigUInt(amount, units: .eth) else {return nil} - var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) - mergedOptions.from = from - return sendETH(to: to, amount: value, extraData: extraData, transactionOptions: mergedOptions) - } - - /** - *Convenience wrapper to send ERC20 tokens to another address. Internally it creates a virtual contract and encodes all the options and data. Assumes that the sender knows the decimal units of the underlying token.* - - - parameters: - - tokenAddress: EthereumAddress of the token contract - - from: EthereumAddress to send tokens from - - to: EthereumAddress to send tokens to - - amount: BigUInt indicating the number of tokens in the the smallest indivisible units (mind that sender knows the number of decimals) - - options: Web3Options to override the default gas price, gas limit. "Value" field of the options is ignored and the "amount" parameter is used instead. "From" parameter is also ignored. - - - returns: - - TransactionIntermediate object - - */ - public func sendERC20tokensWithKnownDecimals(tokenAddress: EthereumAddress, from: EthereumAddress, to: EthereumAddress, amount: BigUInt, transactionOptions: TransactionOptions? = nil) -> WriteTransaction? { - let contract = self.web3.contract(Web3.Utils.erc20ABI, at: tokenAddress, abiVersion: 2) - var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) - mergedOptions.from = from - guard let writeTX = contract?.write("transfer", parameters: [to, amount] as [AnyObject], transactionOptions: mergedOptions) else {return nil} - return writeTX - } - - /** - *Convenience wrapper to send ERC20 tokens to another address. Internally it creates a virtual contract and encodes all the options and data. Pulls the number of decimals of the token under the hood.* - - - parameters: - - tokenAddress: EthereumAddress of the token contract - - from: EthereumAddress to send tokens from - - to: EthereumAddress to send tokens to - - amount: String in "natura" demonimation. It can contain either "," or "." decimal separator. - - options: Web3Options to override the default gas price, gas limit. "Value" field of the options is ignored and the "amount" parameter is used instead. "From" parameter is also ignored. - - - returns: - - TransactionIntermediate object - - - important: This call is synchronous - - * If the amount is "1.01" and token has 9 decimals it will result in sending 1010000000 of the smallest invidisible token units.* - */ - public func sendERC20tokensWithNaturalUnits(tokenAddress: EthereumAddress, from: EthereumAddress, to: EthereumAddress, amount: String, transactionOptions: TransactionOptions? = nil) async throws -> WriteTransaction? { - let contract = self.web3.contract(Web3.Utils.erc20ABI, at: tokenAddress, abiVersion: 2) - var mergedOptions = self.web3.transactionOptions.merge(transactionOptions) - mergedOptions.from = from - let resp = try await contract?.read("decimals", transactionOptions: mergedOptions)?.decodedData() - var decimals = BigUInt(0) - guard let response = resp, let dec = response["0"], let decTyped = dec as? BigUInt else {return nil} - decimals = decTyped - let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else {return nil} - return sendERC20tokensWithKnownDecimals(tokenAddress: tokenAddress, from: from, to: to, amount: value, transactionOptions: mergedOptions) - } - -} From 66119996dc5e63b7f37ca7f1b65429c707e27e46 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 May 2022 20:46:45 +0700 Subject: [PATCH 38/45] Rename deleted methods in tests and BrowserFunctions to new one. Temporary disabled tests that requires temporary deleted methods. --- Sources/web3swift/API/APIMethod.swift | 5 +- .../web3swift/API/APIRequestParameter.swift | 4 +- .../web3swift/API/HexDecodableProtocols.swift | 6 -- .../Web3+BrowserFunctions.swift | 12 +-- Sources/web3swift/Web3/Web3+GasOracle.swift | 2 +- .../localTests/LocalTestCase.swift | 4 +- .../web3swiftAdvancedABIv2Tests.swift | 20 ++--- .../web3swiftBasicLocalNodeTests.swift | 20 ++--- .../localTests/web3swiftEventloopTests.swift | 2 +- .../localTests/web3swiftHelpers.swift | 4 +- .../web3swiftPersonalSignatureTests.swift | 4 +- .../localTests/web3swiftPromisesTests.swift | 60 +++++++-------- .../web3swiftTransactionsTests.swift | 6 +- .../localTests/web3swiftUserCases.swift | 76 ++++++++++--------- .../remoteTests/InfuraTests.swift | 10 +-- 15 files changed, 117 insertions(+), 118 deletions(-) diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 559400e1d..14f338a10 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -13,6 +13,7 @@ public typealias Receipt = Hash public typealias Address = Hash // 20 bytes (40 chars length without 0x) public typealias TransactionHash = Hash // 64 chars length without 0x +// FIXME: Add documentation to each method. /// Ethereum JSON RPC API Calls public enum APIRequest { // MARK: - Official API @@ -91,7 +92,7 @@ public enum APIRequest { extension Data: APIResultType { } extension APIRequest { - public var method: REST { + var method: REST { switch self { default: return .POST } @@ -266,7 +267,7 @@ extension APIRequest { } } -public enum REST: String { +enum REST: String { case POST case GET } diff --git a/Sources/web3swift/API/APIRequestParameter.swift b/Sources/web3swift/API/APIRequestParameter.swift index d16981a81..9cd57fcf7 100644 --- a/Sources/web3swift/API/APIRequestParameter.swift +++ b/Sources/web3swift/API/APIRequestParameter.swift @@ -15,7 +15,6 @@ import Foundation /// Please see `RequestParameter` documentation for more details. protocol APIRequestParameterType: Encodable { } -protocol APIRequestParameterElementType: Encodable { } extension Int: APIRequestParameterType { } @@ -29,6 +28,9 @@ extension Bool: APIRequestParameterType { } extension Array: APIRequestParameterType where Element: APIRequestParameterElementType { } + +protocol APIRequestParameterElementType: Encodable { } + extension TransactionParameters: APIRequestParameterType { } extension EventFilterParameters: APIRequestParameterType { } diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/web3swift/API/HexDecodableProtocols.swift index b1a388f69..45b7ea3f8 100644 --- a/Sources/web3swift/API/HexDecodableProtocols.swift +++ b/Sources/web3swift/API/HexDecodableProtocols.swift @@ -46,12 +46,6 @@ extension BigInt: LiteralInitiableFromString { } extension BigUInt: LiteralInitiableFromString { } -// This don't work without each other. -//extension LiteralInitiableFromString { -// public init?(from hexString: String) { return nil } -//} -//extension Array: LiteralInitiableFromString where Element: LiteralInitiableFromString { } - public protocol IntegerInitableWithRadix { init?(_ text: S, radix: Int) } diff --git a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift index e8a7eec65..f66908191 100755 --- a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift +++ b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift @@ -11,7 +11,7 @@ extension web3.BrowserFunctions { public func getAccounts() async -> [String]? { do { - let accounts = try await self.web3.eth.getAccounts() + let accounts = try await self.web3.eth.ownedAccounts() return accounts.compactMap({$0.address}) } catch { return [String]() @@ -86,7 +86,7 @@ extension web3.BrowserFunctions { public func sendTransaction(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions, password: String = "web3swift") async -> [String: Any]? { do { - let result = try await self.web3.eth.sendTransaction(transaction, transactionOptions: transactionOptions, password: password) + let result = try await self.web3.eth.send(transaction, transactionOptions: transactionOptions, password: password) return ["txhash": result.hash] } catch { return nil @@ -110,7 +110,7 @@ extension web3.BrowserFunctions { public func estimateGas(_ transaction: EthereumTransaction, transactionOptions: TransactionOptions) async -> BigUInt? { do { - let result = try await self.web3.eth.estimateGas(transaction, transactionOptions: transactionOptions) + let result = try await self.web3.eth.estimateGas(for: transaction, transactionOptions: transactionOptions) return result } catch { return nil @@ -133,7 +133,7 @@ extension web3.BrowserFunctions { var transaction = trans var options = opts guard let _ = options.from else {return (nil, nil)} - let gasPrice = try await self.web3.eth.getGasPrice() + let gasPrice = try await self.web3.eth.gasPrice() transaction.parameters.gasPrice = gasPrice options.gasPrice = .manual(gasPrice) guard let gasEstimate = await self.estimateGas(transaction, transactionOptions: options) else {return (nil, nil)} @@ -179,7 +179,7 @@ extension web3.BrowserFunctions { case .manual(let gasPrice): transaction.parameters.gasPrice = gasPrice default: - let gasPrice = try await self.web3.eth.getGasPrice() + let gasPrice = try await self.web3.eth.gasPrice() transaction.parameters.gasPrice = gasPrice } @@ -187,7 +187,7 @@ extension web3.BrowserFunctions { case .manual(let gasLimit): transaction.parameters.gasLimit = gasLimit default: - let gasLimit = try await self.web3.eth.estimateGas(transaction, transactionOptions: transactionOptions) + let gasLimit = try await self.web3.eth.estimateGas(for: transaction, transactionOptions: transactionOptions) transaction.parameters.gasLimit = gasLimit } diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index 31cf17ff1..4f1ec1a29 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -124,7 +124,7 @@ extension Web3 { private func suggestGasFeeLegacy() async throws -> [BigUInt] { var latestBlockNumber: BigUInt = 0 switch block { - case .latest: latestBlockNumber = try await eth.getBlockNumber() + case .latest: latestBlockNumber = try await eth.blockNumber() case let .exact(number): latestBlockNumber = number // FIXME: Make real error here // Error throws since pending and erliest are unable to be used in this method. diff --git a/Tests/web3swiftTests/localTests/LocalTestCase.swift b/Tests/web3swiftTests/localTests/LocalTestCase.swift index 404818eb9..ed13c1f91 100644 --- a/Tests/web3swiftTests/localTests/LocalTestCase.swift +++ b/Tests/web3swiftTests/localTests/LocalTestCase.swift @@ -20,12 +20,12 @@ class LocalTestCase: XCTestCase { let web3 = try! await Web3.new(LocalTestCase.url) - let block = try! await web3.eth.getBlockNumber() + let block = try! await web3.eth.blockNumber() if block >= 25 { return } print("\n ****** Preloading Ganache (\(25 - block) blocks) *****\n") - let allAddresses = try! await web3.eth.getAccounts() + let allAddresses = try! await web3.eth.ownedAccounts() let sendToAddress = allAddresses[0] let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2) let value = Web3.Utils.parseToBigUInt("1.0", units: .eth) diff --git a/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift b/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift index a821ea819..fbaf23280 100755 --- a/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift @@ -17,7 +17,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { let bytecode = Data.fromHex("6080604052341561000f57600080fd5b610cb18061001e6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063189533931461007257806338163ff51461009b57806388be6c65146100c4578063e7c1a47c146100ed578063f376e01314610116575b600080fd5b341561007d57600080fd5b61008561013f565b6040516100929190610a9f565b60405180910390f35b34156100a657600080fd5b6100ae610220565b6040516100bb9190610a7d565b60405180910390f35b34156100cf57600080fd5b6100d76102c5565b6040516100e49190610ae3565b60405180910390f35b34156100f857600080fd5b610100610350565b60405161010d9190610ac1565b60405180910390f35b341561012157600080fd5b610129610399565b6040516101369190610b05565b60405180910390f35b6060600260405190808252806020026020018201604052801561017657816020015b60608152602001906001900390816101615790505b5090506040805190810160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152508160008151811015156101be57fe5b906020019060200201819052506040805190810160405280600581526020017f576f726c6400000000000000000000000000000000000000000000000000000081525081600181518110151561021057fe5b9060200190602002018190525090565b610228610546565b6040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081600060028110151561026d57fe5b60200201819052506040805190810160405280600581526020017f576f726c640000000000000000000000000000000000000000000000000000008152508160016002811015156102ba57fe5b602002018190525090565b6060600260405190808252806020026020018201604052801561030257816020015b6102ef61056d565b8152602001906001900390816102e75790505b50905061030d610399565b81600081518110151561031c57fe5b90602001906020020181905250610331610399565b81600181518110151561034057fe5b9060200190602002018190525090565b6103586105a9565b610360610399565b81600060028110151561036f57fe5b602002018190525061037f610399565b81600160028110151561038e57fe5b602002018190525090565b6103a16105d8565b60606103ab610614565b6103b3610546565b60036040519080825280602002602001820160405280156103e35781602001602082028038833980820191505090505b50925060008360008151811015156103f757fe5b9060200190602002018181525050600183600181518110151561041657fe5b9060200190602002018181525050600283600281518110151561043557fe5b90602001906020020181815250506040805190810160405280600081526020016001815250915060408051908101604052806040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081526020016040805190810160405280600581526020017f576f726c64000000000000000000000000000000000000000000000000000000815250815250905060a060405190810160405280600181526020016040805190810160405280600b81526020017f48656c6c6f20776f726c64000000000000000000000000000000000000000000815250815260200183815260200184815260200182815250935083935050505090565b60408051908101604052806002905b60608152602001906001900390816105555790505090565b60e060405190810160405280600081526020016060815260200161058f610636565b8152602001606081526020016105a3610658565b81525090565b6101c0604051908101604052806002905b6105c261056d565b8152602001906001900390816105ba5790505090565b60e06040519081016040528060008152602001606081526020016105fa610636565b81526020016060815260200161060e610658565b81525090565b6040805190810160405280600290602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b60408051908101604052806002905b60608152602001906001900390816106675790505090565b600061068a82610b81565b8360208202850161069a85610b31565b60005b848110156106d35783830388526106b5838351610930565b92506106c082610bdb565b915060208801975060018101905061069d565b508196508694505050505092915050565b60006106ef82610b76565b836020820285016106ff85610b27565b60005b8481101561073857838303885261071a838351610930565b925061072582610bce565b9150602088019750600181019050610702565b508196508694505050505092915050565b600061075482610b8c565b8084526020840193508360208202850161076d85610b3b565b60005b848110156107a6578383038852610788838351610930565b925061079382610be8565b9150602088019750600181019050610770565b508196508694505050505092915050565b60006107c282610b97565b836020820285016107d285610b48565b60005b8481101561080b5783830388526107ed8383516109ea565b92506107f882610bf5565b91506020880197506001810190506107d5565b508196508694505050505092915050565b600061082782610ba2565b8084526020840193508360208202850161084085610b52565b60005b8481101561087957838303885261085b8383516109ea565b925061086682610c02565b9150602088019750600181019050610843565b508196508694505050505092915050565b61089381610bad565b61089c82610b5f565b60005b828110156108ce576108b2858351610a6e565b6108bb82610c0f565b915060208501945060018101905061089f565b5050505050565b60006108e082610bb8565b8084526020840193506108f283610b69565b60005b8281101561092457610908868351610a6e565b61091182610c1c565b91506020860195506001810190506108f5565b50849250505092915050565b600061093b82610bc3565b80845261094f816020860160208601610c33565b61095881610c66565b602085010191505092915050565b600060c08301600083015161097e6000860182610a6e565b50602083015184820360208601526109968282610930565b91505060408301516109ab604086018261088a565b50606083015184820360808601526109c382826108d5565b915050608083015184820360a08601526109dd82826106e4565b9150508091505092915050565b600060c083016000830151610a026000860182610a6e565b5060208301518482036020860152610a1a8282610930565b9150506040830151610a2f604086018261088a565b5060608301518482036080860152610a4782826108d5565b915050608083015184820360a0860152610a6182826106e4565b9150508091505092915050565b610a7781610c29565b82525050565b60006020820190508181036000830152610a97818461067f565b905092915050565b60006020820190508181036000830152610ab98184610749565b905092915050565b60006020820190508181036000830152610adb81846107b7565b905092915050565b60006020820190508181036000830152610afd818461081c565b905092915050565b60006020820190508181036000830152610b1f8184610966565b905092915050565b6000819050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b600060029050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60005b83811015610c51578082015181840152602081019050610c36565b83811115610c60576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820fdaf8ce6fe282a46498c8066d5b5ac382b69969eee38e1ad03c0d501b27f65366c6578706572696d656e74616cf50037")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -30,7 +30,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -51,7 +51,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { let bytecode = Data.fromHex("6080604052341561000f57600080fd5b610cb18061001e6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063189533931461007257806338163ff51461009b57806388be6c65146100c4578063e7c1a47c146100ed578063f376e01314610116575b600080fd5b341561007d57600080fd5b61008561013f565b6040516100929190610a9f565b60405180910390f35b34156100a657600080fd5b6100ae610220565b6040516100bb9190610a7d565b60405180910390f35b34156100cf57600080fd5b6100d76102c5565b6040516100e49190610ae3565b60405180910390f35b34156100f857600080fd5b610100610350565b60405161010d9190610ac1565b60405180910390f35b341561012157600080fd5b610129610399565b6040516101369190610b05565b60405180910390f35b6060600260405190808252806020026020018201604052801561017657816020015b60608152602001906001900390816101615790505b5090506040805190810160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152508160008151811015156101be57fe5b906020019060200201819052506040805190810160405280600581526020017f576f726c6400000000000000000000000000000000000000000000000000000081525081600181518110151561021057fe5b9060200190602002018190525090565b610228610546565b6040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081600060028110151561026d57fe5b60200201819052506040805190810160405280600581526020017f576f726c640000000000000000000000000000000000000000000000000000008152508160016002811015156102ba57fe5b602002018190525090565b6060600260405190808252806020026020018201604052801561030257816020015b6102ef61056d565b8152602001906001900390816102e75790505b50905061030d610399565b81600081518110151561031c57fe5b90602001906020020181905250610331610399565b81600181518110151561034057fe5b9060200190602002018190525090565b6103586105a9565b610360610399565b81600060028110151561036f57fe5b602002018190525061037f610399565b81600160028110151561038e57fe5b602002018190525090565b6103a16105d8565b60606103ab610614565b6103b3610546565b60036040519080825280602002602001820160405280156103e35781602001602082028038833980820191505090505b50925060008360008151811015156103f757fe5b9060200190602002018181525050600183600181518110151561041657fe5b9060200190602002018181525050600283600281518110151561043557fe5b90602001906020020181815250506040805190810160405280600081526020016001815250915060408051908101604052806040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081526020016040805190810160405280600581526020017f576f726c64000000000000000000000000000000000000000000000000000000815250815250905060a060405190810160405280600181526020016040805190810160405280600b81526020017f48656c6c6f20776f726c64000000000000000000000000000000000000000000815250815260200183815260200184815260200182815250935083935050505090565b60408051908101604052806002905b60608152602001906001900390816105555790505090565b60e060405190810160405280600081526020016060815260200161058f610636565b8152602001606081526020016105a3610658565b81525090565b6101c0604051908101604052806002905b6105c261056d565b8152602001906001900390816105ba5790505090565b60e06040519081016040528060008152602001606081526020016105fa610636565b81526020016060815260200161060e610658565b81525090565b6040805190810160405280600290602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b60408051908101604052806002905b60608152602001906001900390816106675790505090565b600061068a82610b81565b8360208202850161069a85610b31565b60005b848110156106d35783830388526106b5838351610930565b92506106c082610bdb565b915060208801975060018101905061069d565b508196508694505050505092915050565b60006106ef82610b76565b836020820285016106ff85610b27565b60005b8481101561073857838303885261071a838351610930565b925061072582610bce565b9150602088019750600181019050610702565b508196508694505050505092915050565b600061075482610b8c565b8084526020840193508360208202850161076d85610b3b565b60005b848110156107a6578383038852610788838351610930565b925061079382610be8565b9150602088019750600181019050610770565b508196508694505050505092915050565b60006107c282610b97565b836020820285016107d285610b48565b60005b8481101561080b5783830388526107ed8383516109ea565b92506107f882610bf5565b91506020880197506001810190506107d5565b508196508694505050505092915050565b600061082782610ba2565b8084526020840193508360208202850161084085610b52565b60005b8481101561087957838303885261085b8383516109ea565b925061086682610c02565b9150602088019750600181019050610843565b508196508694505050505092915050565b61089381610bad565b61089c82610b5f565b60005b828110156108ce576108b2858351610a6e565b6108bb82610c0f565b915060208501945060018101905061089f565b5050505050565b60006108e082610bb8565b8084526020840193506108f283610b69565b60005b8281101561092457610908868351610a6e565b61091182610c1c565b91506020860195506001810190506108f5565b50849250505092915050565b600061093b82610bc3565b80845261094f816020860160208601610c33565b61095881610c66565b602085010191505092915050565b600060c08301600083015161097e6000860182610a6e565b50602083015184820360208601526109968282610930565b91505060408301516109ab604086018261088a565b50606083015184820360808601526109c382826108d5565b915050608083015184820360a08601526109dd82826106e4565b9150508091505092915050565b600060c083016000830151610a026000860182610a6e565b5060208301518482036020860152610a1a8282610930565b9150506040830151610a2f604086018261088a565b5060608301518482036080860152610a4782826108d5565b915050608083015184820360a0860152610a6182826106e4565b9150508091505092915050565b610a7781610c29565b82525050565b60006020820190508181036000830152610a97818461067f565b905092915050565b60006020820190508181036000830152610ab98184610749565b905092915050565b60006020820190508181036000830152610adb81846107b7565b905092915050565b60006020820190508181036000830152610afd818461081c565b905092915050565b60006020820190508181036000830152610b1f8184610966565b905092915050565b6000819050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b600060029050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60005b83811015610c51578082015181840152602081019050610c36565b83811115610c60576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820fdaf8ce6fe282a46498c8066d5b5ac382b69969eee38e1ad03c0d501b27f65366c6578706572696d656e74616cf50037")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -64,7 +64,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -85,7 +85,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { let bytecode = Data.fromHex("6080604052341561000f57600080fd5b610cb18061001e6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063189533931461007257806338163ff51461009b57806388be6c65146100c4578063e7c1a47c146100ed578063f376e01314610116575b600080fd5b341561007d57600080fd5b61008561013f565b6040516100929190610a9f565b60405180910390f35b34156100a657600080fd5b6100ae610220565b6040516100bb9190610a7d565b60405180910390f35b34156100cf57600080fd5b6100d76102c5565b6040516100e49190610ae3565b60405180910390f35b34156100f857600080fd5b610100610350565b60405161010d9190610ac1565b60405180910390f35b341561012157600080fd5b610129610399565b6040516101369190610b05565b60405180910390f35b6060600260405190808252806020026020018201604052801561017657816020015b60608152602001906001900390816101615790505b5090506040805190810160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152508160008151811015156101be57fe5b906020019060200201819052506040805190810160405280600581526020017f576f726c6400000000000000000000000000000000000000000000000000000081525081600181518110151561021057fe5b9060200190602002018190525090565b610228610546565b6040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081600060028110151561026d57fe5b60200201819052506040805190810160405280600581526020017f576f726c640000000000000000000000000000000000000000000000000000008152508160016002811015156102ba57fe5b602002018190525090565b6060600260405190808252806020026020018201604052801561030257816020015b6102ef61056d565b8152602001906001900390816102e75790505b50905061030d610399565b81600081518110151561031c57fe5b90602001906020020181905250610331610399565b81600181518110151561034057fe5b9060200190602002018190525090565b6103586105a9565b610360610399565b81600060028110151561036f57fe5b602002018190525061037f610399565b81600160028110151561038e57fe5b602002018190525090565b6103a16105d8565b60606103ab610614565b6103b3610546565b60036040519080825280602002602001820160405280156103e35781602001602082028038833980820191505090505b50925060008360008151811015156103f757fe5b9060200190602002018181525050600183600181518110151561041657fe5b9060200190602002018181525050600283600281518110151561043557fe5b90602001906020020181815250506040805190810160405280600081526020016001815250915060408051908101604052806040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081526020016040805190810160405280600581526020017f576f726c64000000000000000000000000000000000000000000000000000000815250815250905060a060405190810160405280600181526020016040805190810160405280600b81526020017f48656c6c6f20776f726c64000000000000000000000000000000000000000000815250815260200183815260200184815260200182815250935083935050505090565b60408051908101604052806002905b60608152602001906001900390816105555790505090565b60e060405190810160405280600081526020016060815260200161058f610636565b8152602001606081526020016105a3610658565b81525090565b6101c0604051908101604052806002905b6105c261056d565b8152602001906001900390816105ba5790505090565b60e06040519081016040528060008152602001606081526020016105fa610636565b81526020016060815260200161060e610658565b81525090565b6040805190810160405280600290602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b60408051908101604052806002905b60608152602001906001900390816106675790505090565b600061068a82610b81565b8360208202850161069a85610b31565b60005b848110156106d35783830388526106b5838351610930565b92506106c082610bdb565b915060208801975060018101905061069d565b508196508694505050505092915050565b60006106ef82610b76565b836020820285016106ff85610b27565b60005b8481101561073857838303885261071a838351610930565b925061072582610bce565b9150602088019750600181019050610702565b508196508694505050505092915050565b600061075482610b8c565b8084526020840193508360208202850161076d85610b3b565b60005b848110156107a6578383038852610788838351610930565b925061079382610be8565b9150602088019750600181019050610770565b508196508694505050505092915050565b60006107c282610b97565b836020820285016107d285610b48565b60005b8481101561080b5783830388526107ed8383516109ea565b92506107f882610bf5565b91506020880197506001810190506107d5565b508196508694505050505092915050565b600061082782610ba2565b8084526020840193508360208202850161084085610b52565b60005b8481101561087957838303885261085b8383516109ea565b925061086682610c02565b9150602088019750600181019050610843565b508196508694505050505092915050565b61089381610bad565b61089c82610b5f565b60005b828110156108ce576108b2858351610a6e565b6108bb82610c0f565b915060208501945060018101905061089f565b5050505050565b60006108e082610bb8565b8084526020840193506108f283610b69565b60005b8281101561092457610908868351610a6e565b61091182610c1c565b91506020860195506001810190506108f5565b50849250505092915050565b600061093b82610bc3565b80845261094f816020860160208601610c33565b61095881610c66565b602085010191505092915050565b600060c08301600083015161097e6000860182610a6e565b50602083015184820360208601526109968282610930565b91505060408301516109ab604086018261088a565b50606083015184820360808601526109c382826108d5565b915050608083015184820360a08601526109dd82826106e4565b9150508091505092915050565b600060c083016000830151610a026000860182610a6e565b5060208301518482036020860152610a1a8282610930565b9150506040830151610a2f604086018261088a565b5060608301518482036080860152610a4782826108d5565b915050608083015184820360a0860152610a6182826106e4565b9150508091505092915050565b610a7781610c29565b82525050565b60006020820190508181036000830152610a97818461067f565b905092915050565b60006020820190508181036000830152610ab98184610749565b905092915050565b60006020820190508181036000830152610adb81846107b7565b905092915050565b60006020820190508181036000830152610afd818461081c565b905092915050565b60006020820190508181036000830152610b1f8184610966565b905092915050565b6000819050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b600060029050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60005b83811015610c51578082015181840152602081019050610c36565b83811115610c60576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820fdaf8ce6fe282a46498c8066d5b5ac382b69969eee38e1ad03c0d501b27f65366c6578706572696d656e74616cf50037")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -98,7 +98,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -119,7 +119,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { let bytecode = Data.fromHex("6080604052341561000f57600080fd5b610cb18061001e6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063189533931461007257806338163ff51461009b57806388be6c65146100c4578063e7c1a47c146100ed578063f376e01314610116575b600080fd5b341561007d57600080fd5b61008561013f565b6040516100929190610a9f565b60405180910390f35b34156100a657600080fd5b6100ae610220565b6040516100bb9190610a7d565b60405180910390f35b34156100cf57600080fd5b6100d76102c5565b6040516100e49190610ae3565b60405180910390f35b34156100f857600080fd5b610100610350565b60405161010d9190610ac1565b60405180910390f35b341561012157600080fd5b610129610399565b6040516101369190610b05565b60405180910390f35b6060600260405190808252806020026020018201604052801561017657816020015b60608152602001906001900390816101615790505b5090506040805190810160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152508160008151811015156101be57fe5b906020019060200201819052506040805190810160405280600581526020017f576f726c6400000000000000000000000000000000000000000000000000000081525081600181518110151561021057fe5b9060200190602002018190525090565b610228610546565b6040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081600060028110151561026d57fe5b60200201819052506040805190810160405280600581526020017f576f726c640000000000000000000000000000000000000000000000000000008152508160016002811015156102ba57fe5b602002018190525090565b6060600260405190808252806020026020018201604052801561030257816020015b6102ef61056d565b8152602001906001900390816102e75790505b50905061030d610399565b81600081518110151561031c57fe5b90602001906020020181905250610331610399565b81600181518110151561034057fe5b9060200190602002018190525090565b6103586105a9565b610360610399565b81600060028110151561036f57fe5b602002018190525061037f610399565b81600160028110151561038e57fe5b602002018190525090565b6103a16105d8565b60606103ab610614565b6103b3610546565b60036040519080825280602002602001820160405280156103e35781602001602082028038833980820191505090505b50925060008360008151811015156103f757fe5b9060200190602002018181525050600183600181518110151561041657fe5b9060200190602002018181525050600283600281518110151561043557fe5b90602001906020020181815250506040805190810160405280600081526020016001815250915060408051908101604052806040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081526020016040805190810160405280600581526020017f576f726c64000000000000000000000000000000000000000000000000000000815250815250905060a060405190810160405280600181526020016040805190810160405280600b81526020017f48656c6c6f20776f726c64000000000000000000000000000000000000000000815250815260200183815260200184815260200182815250935083935050505090565b60408051908101604052806002905b60608152602001906001900390816105555790505090565b60e060405190810160405280600081526020016060815260200161058f610636565b8152602001606081526020016105a3610658565b81525090565b6101c0604051908101604052806002905b6105c261056d565b8152602001906001900390816105ba5790505090565b60e06040519081016040528060008152602001606081526020016105fa610636565b81526020016060815260200161060e610658565b81525090565b6040805190810160405280600290602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b60408051908101604052806002905b60608152602001906001900390816106675790505090565b600061068a82610b81565b8360208202850161069a85610b31565b60005b848110156106d35783830388526106b5838351610930565b92506106c082610bdb565b915060208801975060018101905061069d565b508196508694505050505092915050565b60006106ef82610b76565b836020820285016106ff85610b27565b60005b8481101561073857838303885261071a838351610930565b925061072582610bce565b9150602088019750600181019050610702565b508196508694505050505092915050565b600061075482610b8c565b8084526020840193508360208202850161076d85610b3b565b60005b848110156107a6578383038852610788838351610930565b925061079382610be8565b9150602088019750600181019050610770565b508196508694505050505092915050565b60006107c282610b97565b836020820285016107d285610b48565b60005b8481101561080b5783830388526107ed8383516109ea565b92506107f882610bf5565b91506020880197506001810190506107d5565b508196508694505050505092915050565b600061082782610ba2565b8084526020840193508360208202850161084085610b52565b60005b8481101561087957838303885261085b8383516109ea565b925061086682610c02565b9150602088019750600181019050610843565b508196508694505050505092915050565b61089381610bad565b61089c82610b5f565b60005b828110156108ce576108b2858351610a6e565b6108bb82610c0f565b915060208501945060018101905061089f565b5050505050565b60006108e082610bb8565b8084526020840193506108f283610b69565b60005b8281101561092457610908868351610a6e565b61091182610c1c565b91506020860195506001810190506108f5565b50849250505092915050565b600061093b82610bc3565b80845261094f816020860160208601610c33565b61095881610c66565b602085010191505092915050565b600060c08301600083015161097e6000860182610a6e565b50602083015184820360208601526109968282610930565b91505060408301516109ab604086018261088a565b50606083015184820360808601526109c382826108d5565b915050608083015184820360a08601526109dd82826106e4565b9150508091505092915050565b600060c083016000830151610a026000860182610a6e565b5060208301518482036020860152610a1a8282610930565b9150506040830151610a2f604086018261088a565b5060608301518482036080860152610a4782826108d5565b915050608083015184820360a0860152610a6182826106e4565b9150508091505092915050565b610a7781610c29565b82525050565b60006020820190508181036000830152610a97818461067f565b905092915050565b60006020820190508181036000830152610ab98184610749565b905092915050565b60006020820190508181036000830152610adb81846107b7565b905092915050565b60006020820190508181036000830152610afd818461081c565b905092915050565b60006020820190508181036000830152610b1f8184610966565b905092915050565b6000819050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b600060029050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60005b83811015610c51578082015181840152602081019050610c36565b83811115610c60576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820fdaf8ce6fe282a46498c8066d5b5ac382b69969eee38e1ad03c0d501b27f65366c6578706572696d656e74616cf50037")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -132,7 +132,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -153,7 +153,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { let bytecode = Data.fromHex("6080604052341561000f57600080fd5b610cb18061001e6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063189533931461007257806338163ff51461009b57806388be6c65146100c4578063e7c1a47c146100ed578063f376e01314610116575b600080fd5b341561007d57600080fd5b61008561013f565b6040516100929190610a9f565b60405180910390f35b34156100a657600080fd5b6100ae610220565b6040516100bb9190610a7d565b60405180910390f35b34156100cf57600080fd5b6100d76102c5565b6040516100e49190610ae3565b60405180910390f35b34156100f857600080fd5b610100610350565b60405161010d9190610ac1565b60405180910390f35b341561012157600080fd5b610129610399565b6040516101369190610b05565b60405180910390f35b6060600260405190808252806020026020018201604052801561017657816020015b60608152602001906001900390816101615790505b5090506040805190810160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152508160008151811015156101be57fe5b906020019060200201819052506040805190810160405280600581526020017f576f726c6400000000000000000000000000000000000000000000000000000081525081600181518110151561021057fe5b9060200190602002018190525090565b610228610546565b6040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081600060028110151561026d57fe5b60200201819052506040805190810160405280600581526020017f576f726c640000000000000000000000000000000000000000000000000000008152508160016002811015156102ba57fe5b602002018190525090565b6060600260405190808252806020026020018201604052801561030257816020015b6102ef61056d565b8152602001906001900390816102e75790505b50905061030d610399565b81600081518110151561031c57fe5b90602001906020020181905250610331610399565b81600181518110151561034057fe5b9060200190602002018190525090565b6103586105a9565b610360610399565b81600060028110151561036f57fe5b602002018190525061037f610399565b81600160028110151561038e57fe5b602002018190525090565b6103a16105d8565b60606103ab610614565b6103b3610546565b60036040519080825280602002602001820160405280156103e35781602001602082028038833980820191505090505b50925060008360008151811015156103f757fe5b9060200190602002018181525050600183600181518110151561041657fe5b9060200190602002018181525050600283600281518110151561043557fe5b90602001906020020181815250506040805190810160405280600081526020016001815250915060408051908101604052806040805190810160405280600581526020017f48656c6c6f00000000000000000000000000000000000000000000000000000081525081526020016040805190810160405280600581526020017f576f726c64000000000000000000000000000000000000000000000000000000815250815250905060a060405190810160405280600181526020016040805190810160405280600b81526020017f48656c6c6f20776f726c64000000000000000000000000000000000000000000815250815260200183815260200184815260200182815250935083935050505090565b60408051908101604052806002905b60608152602001906001900390816105555790505090565b60e060405190810160405280600081526020016060815260200161058f610636565b8152602001606081526020016105a3610658565b81525090565b6101c0604051908101604052806002905b6105c261056d565b8152602001906001900390816105ba5790505090565b60e06040519081016040528060008152602001606081526020016105fa610636565b81526020016060815260200161060e610658565b81525090565b6040805190810160405280600290602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b60408051908101604052806002905b60608152602001906001900390816106675790505090565b600061068a82610b81565b8360208202850161069a85610b31565b60005b848110156106d35783830388526106b5838351610930565b92506106c082610bdb565b915060208801975060018101905061069d565b508196508694505050505092915050565b60006106ef82610b76565b836020820285016106ff85610b27565b60005b8481101561073857838303885261071a838351610930565b925061072582610bce565b9150602088019750600181019050610702565b508196508694505050505092915050565b600061075482610b8c565b8084526020840193508360208202850161076d85610b3b565b60005b848110156107a6578383038852610788838351610930565b925061079382610be8565b9150602088019750600181019050610770565b508196508694505050505092915050565b60006107c282610b97565b836020820285016107d285610b48565b60005b8481101561080b5783830388526107ed8383516109ea565b92506107f882610bf5565b91506020880197506001810190506107d5565b508196508694505050505092915050565b600061082782610ba2565b8084526020840193508360208202850161084085610b52565b60005b8481101561087957838303885261085b8383516109ea565b925061086682610c02565b9150602088019750600181019050610843565b508196508694505050505092915050565b61089381610bad565b61089c82610b5f565b60005b828110156108ce576108b2858351610a6e565b6108bb82610c0f565b915060208501945060018101905061089f565b5050505050565b60006108e082610bb8565b8084526020840193506108f283610b69565b60005b8281101561092457610908868351610a6e565b61091182610c1c565b91506020860195506001810190506108f5565b50849250505092915050565b600061093b82610bc3565b80845261094f816020860160208601610c33565b61095881610c66565b602085010191505092915050565b600060c08301600083015161097e6000860182610a6e565b50602083015184820360208601526109968282610930565b91505060408301516109ab604086018261088a565b50606083015184820360808601526109c382826108d5565b915050608083015184820360a08601526109dd82826106e4565b9150508091505092915050565b600060c083016000830151610a026000860182610a6e565b5060208301518482036020860152610a1a8282610930565b9150506040830151610a2f604086018261088a565b5060608301518482036080860152610a4782826108d5565b915050608083015184820360a0860152610a6182826106e4565b9150508091505092915050565b610a7781610c29565b82525050565b60006020820190508181036000830152610a97818461067f565b905092915050565b60006020820190508181036000830152610ab98184610749565b905092915050565b60006020820190508181036000830152610adb81846107b7565b905092915050565b60006020820190508181036000830152610afd818461081c565b905092915050565b60006020820190508181036000830152610b1f8184610966565b905092915050565b6000819050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b600060029050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60005b83811015610c51578082015181840152602081019050610c36565b83811115610c60576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820fdaf8ce6fe282a46498c8066d5b5ac382b69969eee38e1ad03c0d501b27f65366c6578706572696d656e74616cf50037")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -166,7 +166,7 @@ class web3swiftAdvancedABIv2Tests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { diff --git a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift index ef1df2248..ca3d2cce7 100755 --- a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift @@ -16,7 +16,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { func testDeployWithRemoteSigning() async throws { let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let abiString = "[{\"constant\":true,\"inputs\":[],\"name\":\"getFlagData\",\"outputs\":[{\"name\":\"data\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"data\",\"type\":\"string\"}],\"name\":\"setFlagData\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" let bytecode = Data.fromHex("6060604052341561000f57600080fd5b6103358061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a16e94bf14610051578063a46b5b6b146100df575b600080fd5b341561005c57600080fd5b61006461013c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100a4578082015181840152602081019050610089565b50505050905090810190601f1680156100d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100ea57600080fd5b61013a600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190505061020d565b005b610144610250565b6000808073ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102035780601f106101d857610100808354040283529160200191610203565b820191906000526020600020905b8154815290600101906020018083116101e657829003601f168201915b5050505050905090565b806000808073ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001908051906020019061024c929190610264565b5050565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102a557805160ff19168380011785556102d3565b828001600101855582156102d3579182015b828111156102d25782518255916020019190600101906102b7565b5b5090506102e091906102e4565b5090565b61030691905b808211156103025760008160009055506001016102ea565b5090565b905600a165627a7a7230582017359d063cd7fdf56f19ca186a54863ce855c8f070acece905d8538fbbc4d1bf0029")! @@ -34,7 +34,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -44,13 +44,13 @@ class web3swiftBasicLocalNodeTests: XCTestCase { break } - let details = try await web3.eth.getTransactionDetails(txHash) + let details = try await web3.eth.transactionDetails(txHash) print(details) } func testEthSendExampleWithRemoteSigning() async throws { let web3 = try await Web3.new(URL(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! @@ -72,7 +72,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -82,7 +82,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { break } - let details = try await web3.eth.getTransactionDetails(txHash) + let details = try await web3.eth.transactionDetails(txHash) print(details) @@ -100,7 +100,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { // FIXME: Fails on ganache // func testSignPersonal() throws { // let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - // let allAddresses = try web3.eth.getAccounts() + // let allAddresses = try web3.eth.ownedAccounts() // let response = try web3.personal.signPersonalMessage(message: "hello world".data(using: .utf8)!, from: allAddresses[0]) @@ -110,7 +110,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { // MARK: Ganache doesn't support a mempool for now // func testTxPoolStatus() throws { // let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) -// let allAddresses = try web3.eth.getAccounts() +// let allAddresses = try web3.eth.ownedAccounts() // // let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! // let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! @@ -131,7 +131,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { // // func testTxPoolInspect() throws { // let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) -// let allAddresses = try web3.eth.getAccounts() +// let allAddresses = try web3.eth.ownedAccounts() // // let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! // let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! @@ -152,7 +152,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { // // func testTxPoolContent() throws { // let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) -// let allAddresses = try web3.eth.getAccounts() +// let allAddresses = try web3.eth.ownedAccounts() // // let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! // let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! diff --git a/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift b/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift index 068412d29..d9e76d9bf 100755 --- a/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift @@ -15,7 +15,7 @@ class web3swiftEventloopTests: XCTestCase { let expectation = self.expectation(description: "Waiting") func getBlockNumber(_ web3: web3) async { do { - let blockNumber = try await web3.eth.getBlockNumber() + let blockNumber = try await web3.eth.blockNumber() print("Block number = " + String(blockNumber)) ticksToWait = ticksToWait - 1 if ticksToWait == 0 { diff --git a/Tests/web3swiftTests/localTests/web3swiftHelpers.swift b/Tests/web3swiftTests/localTests/web3swiftHelpers.swift index 997c57e32..71864fe9d 100644 --- a/Tests/web3swiftTests/localTests/web3swiftHelpers.swift +++ b/Tests/web3swiftTests/localTests/web3swiftHelpers.swift @@ -17,7 +17,7 @@ class web3swiftHelpers { let bytecode = Data.fromHex("60806040523480156200001157600080fd5b5060405162001f0c38038062001f0c8339818101604052810190620000379190620003af565b83600490805190602001906200004f9291906200025f565b508260059080519060200190620000689291906200025f565b5033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146200012b576000811162000125576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200011c90620004ce565b60405180910390fd5b620001aa565b6000811115620001a957600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200019f90620004ac565b60405180910390fd5b5b5b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200024d9190620004f0565b60405180910390a3505050506200079e565b8280546200026d90620005f1565b90600052602060002090601f016020900481019282620002915760008555620002dd565b82601f10620002ac57805160ff1916838001178555620002dd565b82800160010185558215620002dd579182015b82811115620002dc578251825591602001919060010190620002bf565b5b509050620002ec9190620002f0565b5090565b5b808211156200030b576000816000905550600101620002f1565b5090565b600062000326620003208462000536565b6200050d565b9050828152602081018484840111156200033f57600080fd5b6200034c848285620005bb565b509392505050565b60008151905062000365816200076a565b92915050565b600082601f8301126200037d57600080fd5b81516200038f8482602086016200030f565b91505092915050565b600081519050620003a98162000784565b92915050565b60008060008060808587031215620003c657600080fd5b600085015167ffffffffffffffff811115620003e157600080fd5b620003ef878288016200036b565b945050602085015167ffffffffffffffff8111156200040d57600080fd5b6200041b878288016200036b565b93505060406200042e8782880162000354565b9250506060620004418782880162000398565b91505092959194509250565b60006200045c6037836200056c565b91506200046982620006cc565b604082019050919050565b600062000483602e836200056c565b915062000490826200071b565b604082019050919050565b620004a681620005b1565b82525050565b60006020820190508181036000830152620004c7816200044d565b9050919050565b60006020820190508181036000830152620004e98162000474565b9050919050565b60006020820190506200050760008301846200049b565b92915050565b6000620005196200052c565b905062000527828262000627565b919050565b6000604051905090565b600067ffffffffffffffff8211156200055457620005536200068c565b5b6200055f82620006bb565b9050602081019050919050565b600082825260208201905092915050565b60006200058a8262000591565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015620005db578082015181840152602081019050620005be565b83811115620005eb576000848401525b50505050565b600060028204905060018216806200060a57607f821691505b602082108114156200062157620006206200065d565b5b50919050565b6200063282620006bb565b810181811067ffffffffffffffff821117156200065457620006536200068c565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f45524332303a206d696e7420726563697069656e7420697320656d7074792c2060008201527f627574206d696e7420616d6f756e742069736e27742030000000000000000000602082015250565b7f45524332303a206d696e7420616d6f756e74206973203020746f206e6f6e2d6560008201527f6d70747920726563697069656e74000000000000000000000000000000000000602082015250565b62000775816200057d565b81146200078157600080fd5b50565b6200078f81620005b1565b81146200079b57600080fd5b50565b61175e80620007ae6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806340c10f191161008c578063a457c2d711610066578063a457c2d714610228578063a9059cbb14610258578063dd62ed3e14610288578063f2fde38b146102b8576100cf565b806340c10f19146101be57806370a08231146101da57806395d89b411461020a576100cf565b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461012257806323b872dd14610140578063313ce56714610170578063395093511461018e575b600080fd5b6100dc6102d4565b6040516100e9919061116c565b60405180910390f35b61010c60048036038101906101079190610f74565b610366565b6040516101199190611151565b60405180910390f35b61012a610384565b60405161013791906112ae565b60405180910390f35b61015a60048036038101906101559190610f25565b61038e565b6040516101679190611151565b60405180910390f35b610178610486565b60405161018591906112c9565b60405180910390f35b6101a860048036038101906101a39190610f74565b61048f565b6040516101b59190611151565b60405180910390f35b6101d860048036038101906101d39190610f74565b61053b565b005b6101f460048036038101906101ef9190610ec0565b6106fa565b60405161020191906112ae565b60405180910390f35b610212610742565b60405161021f919061116c565b60405180910390f35b610242600480360381019061023d9190610f74565b6107d4565b60405161024f9190611151565b60405180910390f35b610272600480360381019061026d9190610f74565b6108bf565b60405161027f9190611151565b60405180910390f35b6102a2600480360381019061029d9190610ee9565b6108dd565b6040516102af91906112ae565b60405180910390f35b6102d260048036038101906102cd9190610ec0565b610964565b005b6060600480546102e3906113de565b80601f016020809104026020016040519081016040528092919081815260200182805461030f906113de565b801561035c5780601f106103315761010080835404028352916020019161035c565b820191906000526020600020905b81548152906001019060200180831161033f57829003601f168201915b5050505050905090565b600061037a610373610a38565b8484610a40565b6001905092915050565b6000600254905090565b600061039b848484610c0b565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006103e6610a38565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015610466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045d9061120e565b60405180910390fd5b61047a85610472610a38565b858403610a40565b60019150509392505050565b60006012905090565b600061053161049c610a38565b8484600160006104aa610a38565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461052c9190611300565b610a40565b6001905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105c2906111ee565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561063b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106329061128e565b60405180910390fd5b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546106899190611300565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516106ee91906112ae565b60405180910390a35050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060058054610751906113de565b80601f016020809104026020016040519081016040528092919081815260200182805461077d906113de565b80156107ca5780601f1061079f576101008083540402835291602001916107ca565b820191906000526020600020905b8154815290600101906020018083116107ad57829003601f168201915b5050505050905090565b600080600160006107e3610a38565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050828110156108a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108979061126e565b60405180910390fd5b6108b46108ab610a38565b85858403610a40565b600191505092915050565b60006108d36108cc610a38565b8484610c0b565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109eb906111ee565b60405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610ab0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa79061124e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610b20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b17906111ae565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610bfe91906112ae565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c729061122e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ceb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce29061118e565b60405180910390fd5b610cf6838383610e8c565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015610d7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d73906111ce565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610e0f9190611300565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e7391906112ae565b60405180910390a3610e86848484610e91565b50505050565b505050565b505050565b600081359050610ea5816116fa565b92915050565b600081359050610eba81611711565b92915050565b600060208284031215610ed257600080fd5b6000610ee084828501610e96565b91505092915050565b60008060408385031215610efc57600080fd5b6000610f0a85828601610e96565b9250506020610f1b85828601610e96565b9150509250929050565b600080600060608486031215610f3a57600080fd5b6000610f4886828701610e96565b9350506020610f5986828701610e96565b9250506040610f6a86828701610eab565b9150509250925092565b60008060408385031215610f8757600080fd5b6000610f9585828601610e96565b9250506020610fa685828601610eab565b9150509250929050565b610fb981611368565b82525050565b6000610fca826112e4565b610fd481856112ef565b9350610fe48185602086016113ab565b610fed8161146e565b840191505092915050565b60006110056023836112ef565b91506110108261147f565b604082019050919050565b60006110286022836112ef565b9150611033826114ce565b604082019050919050565b600061104b6026836112ef565b91506110568261151d565b604082019050919050565b600061106e6010836112ef565b91506110798261156c565b602082019050919050565b60006110916028836112ef565b915061109c82611595565b604082019050919050565b60006110b46025836112ef565b91506110bf826115e4565b604082019050919050565b60006110d76024836112ef565b91506110e282611633565b604082019050919050565b60006110fa6025836112ef565b915061110582611682565b604082019050919050565b600061111d601f836112ef565b9150611128826116d1565b602082019050919050565b61113c81611394565b82525050565b61114b8161139e565b82525050565b60006020820190506111666000830184610fb0565b92915050565b600060208201905081810360008301526111868184610fbf565b905092915050565b600060208201905081810360008301526111a781610ff8565b9050919050565b600060208201905081810360008301526111c78161101b565b9050919050565b600060208201905081810360008301526111e78161103e565b9050919050565b6000602082019050818103600083015261120781611061565b9050919050565b6000602082019050818103600083015261122781611084565b9050919050565b60006020820190508181036000830152611247816110a7565b9050919050565b60006020820190508181036000830152611267816110ca565b9050919050565b60006020820190508181036000830152611287816110ed565b9050919050565b600060208201905081810360008301526112a781611110565b9050919050565b60006020820190506112c36000830184611133565b92915050565b60006020820190506112de6000830184611142565b92915050565b600081519050919050565b600082825260208201905092915050565b600061130b82611394565b915061131683611394565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561134b5761134a611410565b5b828201905092915050565b600061136182611374565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b838110156113c95780820151818401526020810190506113ae565b838111156113d8576000848401525b50505050565b600060028204905060018216806113f657607f821691505b6020821081141561140a5761140961143f565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f8301169050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a204e6f74206f776e657200000000000000000000000000000000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206160008201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b61170381611356565b811461170e57600080fd5b50565b61171a81611394565b811461172557600080fd5b5056fea2646970667358221220b6ac3a3baa1a92f9f5628a993657177a7d65adf57696ee461d89686f85a28d6164736f6c63430008040033")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [ @@ -35,7 +35,7 @@ class web3swiftHelpers { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { diff --git a/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift b/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift index 07981f56a..697cbc422 100755 --- a/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift @@ -39,7 +39,7 @@ class web3swiftPersonalSignatureTests: XCTestCase { var contract = web3.contract(abiString, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] let deployTx = contract.deploy(bytecode: bytecode, parameters: parameters)! - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() deployTx.transactionOptions.from = allAddresses[0] deployTx.transactionOptions.gasLimit = .manual(3000000) let deployResult = try await deployTx.send() @@ -48,7 +48,7 @@ class web3swiftPersonalSignatureTests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { diff --git a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift index 92430efc9..de4c79512 100755 --- a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift @@ -21,21 +21,21 @@ class web3swiftPromisesTests: XCTestCase { let balance = try await web3.eth.getBalance(for: "0xe22b8979739D724343bd002F9f432F5990879901") print(balance) } - - func testGetTransactionDetailsPromise() async throws { - let gasLimit = BigUInt(78423) - let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - let allAddresses = try await web3.eth.getAccounts() - guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} - writeTX.transactionOptions.from = allAddresses[0] - writeTX.transactionOptions.gasLimit = .manual(gasLimit) - let writeResult = try await writeTX.send() - let txHash = writeResult.hash - let result = try await web3.eth.transactionDetails(txHash) - print(result) - XCTAssert(result.transaction.parameters.gasLimit == BigUInt(gasLimit)) - } + // FIXME: Temporary deleted method `sendETH` should be restored. +// func testGetTransactionDetailsPromise() async throws { +// let gasLimit = BigUInt(78423) +// let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) +// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! +// let allAddresses = try await web3.eth.ownedAccounts() +// guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} +// writeTX.transactionOptions.from = allAddresses[0] +// writeTX.transactionOptions.gasLimit = .manual(gasLimit) +// let writeResult = try await writeTX.send() +// let txHash = writeResult.hash +// let result = try await web3.eth.transactionDetails(txHash) +// print(result) +// XCTAssert(result.transaction.parameters.gasLimit == BigUInt(gasLimit)) +// } func testEstimateGasPromise() async throws { let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) @@ -57,7 +57,7 @@ class web3swiftPromisesTests: XCTestCase { let bytecode = Data.fromHex("0x608060405234801561001057600080fd5b50610100806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630dbe671f8114605757806329e99f0714607b5780634df7e3d0146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960ce565b60005481565b803a111560ba57600160005560cb565b803a101560cb576001600081905580555b50565b600154815600a165627a7a723058200327a504a24f70cf740239fad2ad203f21caf0ef05f7870bd88482f6fa3cf1080029")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let contract = web3.contract(Web3.Utils.estimateGasTestABI, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -70,7 +70,7 @@ class web3swiftPromisesTests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) switch receipt.status { @@ -117,19 +117,19 @@ class web3swiftPromisesTests: XCTestCase { print(estimate2) XCTAssert(estimate2 - estimate1 <= 22000) } - - func testSendETHPromise() async throws { - let web3 = try await Web3.new(URL(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() - let gasPrice = try await web3.eth.getGasPrice() - let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} - writeTX.transactionOptions.from = allAddresses[0] - writeTX.transactionOptions.gasPrice = .manual(gasPrice) - let result = try await writeTX.send() - print(result) - } - + // FIXME: Temporary deleted method `sendETH` should be restored. +// func testSendETHPromise() async throws { +// let web3 = try await Web3.new(URL(string: "http://127.0.0.1:8545")!) +// let allAddresses = try await web3.eth.ownedAccounts() +// let gasPrice = try await web3.eth.gasPrice() +// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! +// guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} +// writeTX.transactionOptions.from = allAddresses[0] +// writeTX.transactionOptions.gasPrice = .manual(gasPrice) +// let result = try await writeTX.send() +// print(result) +// } +// func testERC20tokenBalancePromise() async throws { let (web3, _, receipt, _) = try await web3swiftHelpers.localDeployERC20() diff --git a/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift b/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift index 5cd0a2603..3d79ea29e 100755 --- a/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift @@ -627,7 +627,7 @@ class web3swiftTransactionsTests: XCTestCase { do { let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2) let value = Web3.Utils.parseToBigUInt("1.0", units: .eth) let from = allAddresses[0] @@ -641,7 +641,7 @@ class web3swiftTransactionsTests: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) XCTAssert(receipt.status == .ok) @@ -652,7 +652,7 @@ class web3swiftTransactionsTests: XCTestCase { break } - let details = try await web3.eth.getTransactionDetails(txHash) + let details = try await web3.eth.transactionDetails(txHash) print(details) let txnGasLimit = details.transaction.parameters.gasLimit XCTAssert(txnGasLimit == BigUInt(78423)) diff --git a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift index a3728cb6b..2c66add50 100755 --- a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift +++ b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift @@ -35,46 +35,48 @@ class web3swiftUserCases: XCTestCase { let web3 = try? await Web3.new(url) XCTAssert(web3 != nil, "Failed to create web3 for custom provider") } - - func testProperGasLimit() async throws { - let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() - let gasPrice = try await web3.eth.getGasPrice() - let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} - writeTX.transactionOptions.from = allAddresses[0] - writeTX.transactionOptions.gasPrice = .manual(gasPrice) - let gasEstimate = try await writeTX.estimateGas(with: nil) - writeTX.transactionOptions.gasLimit = .manual(gasEstimate + 1234) - let assembled = try await writeTX.assembleTransaction() - XCTAssert(assembled.gasLimit == gasEstimate + 1234) - } - - func testProperGasPrice() async throws { - let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() - let gasPrice = try await web3.eth.getGasPrice() - let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else { - return XCTFail() - } - writeTX.transactionOptions.from = allAddresses[0] - writeTX.transactionOptions.gasPrice = .manual(gasPrice * 2) - let gasEstimate = try await writeTX.estimateGas(with: nil) - writeTX.transactionOptions.gasLimit = .manual(gasEstimate + 1234) - let assembled = try await writeTX.assembleTransaction() - let txnGasLimit = assembled.parameters.gasLimit - let txnGasPrice = assembled.parameters.gasPrice - - XCTAssert(txnGasLimit == gasEstimate + 1234) - XCTAssert(txnGasPrice == gasPrice * 2) - } + + // FIXME: Temporary deleted method `sendETH` should be restored. +// func testProperGasLimit() async throws { +// let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) +// let allAddresses = try await web3.eth.ownedAccounts() +// let gasPrice = try await web3.eth.gasPrice() +// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! +// guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else {return XCTFail()} +// writeTX.transactionOptions.from = allAddresses[0] +// writeTX.transactionOptions.gasPrice = .manual(gasPrice) +// let gasEstimate = try await writeTX.estimateGas(with: nil) +// writeTX.transactionOptions.gasLimit = .manual(gasEstimate + 1234) +// let assembled = try await writeTX.assembleTransaction() +// XCTAssert(assembled.gasLimit == gasEstimate + 1234) +// } + + // FIXME: Temporary deleted method `sendETH` should be restored. +// func testProperGasPrice() async throws { +// let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) +// let allAddresses = try await web3.eth.ownedAccounts() +// let gasPrice = try await web3.eth.gasPrice() +// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! +// guard let writeTX = web3.eth.sendETH(to: sendToAddress, amount: "0.001") else { +// return XCTFail() +// } +// writeTX.transactionOptions.from = allAddresses[0] +// writeTX.transactionOptions.gasPrice = .manual(gasPrice * 2) +// let gasEstimate = try await writeTX.estimateGas(with: nil) +// writeTX.transactionOptions.gasLimit = .manual(gasEstimate + 1234) +// let assembled = try await writeTX.assembleTransaction() +// let txnGasLimit = assembled.parameters.gasLimit +// let txnGasPrice = assembled.parameters.gasPrice +// +// XCTAssert(txnGasLimit == gasEstimate + 1234) +// XCTAssert(txnGasPrice == gasPrice * 2) +// } func testParseTransactionDetailsForContractCreation() async throws {// Deploy contract let bytecode = Data.fromHex("0x608060405234801561001057600080fd5b50610100806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630dbe671f8114605757806329e99f0714607b5780634df7e3d0146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960ce565b60005481565b803a111560ba57600160005560cb565b803a101560cb576001600081905580555b50565b600154815600a165627a7a723058200327a504a24f70cf740239fad2ad203f21caf0ef05f7870bd88482f6fa3cf1080029")! let web3 = try await Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - let allAddresses = try await web3.eth.getAccounts() + let allAddresses = try await web3.eth.ownedAccounts() let contract = web3.contract(Web3.Utils.estimateGasTestABI, at: nil, abiVersion: 2)! let parameters = [] as [AnyObject] @@ -87,7 +89,7 @@ class web3swiftUserCases: XCTestCase { Thread.sleep(forTimeInterval: 1.0) - let receipt = try await web3.eth.getTransactionReceipt(txHash) + let receipt = try await web3.eth.transactionReceipt(txHash) print(receipt) XCTAssert(receipt.contractAddress != nil) @@ -98,7 +100,7 @@ class web3swiftUserCases: XCTestCase { break } - let details = try await web3.eth.getTransactionDetails(txHash) + let details = try await web3.eth.transactionDetails(txHash) print(details) XCTAssert(details.transaction.to == .contractDeploymentAddress()) } diff --git a/Tests/web3swiftTests/remoteTests/InfuraTests.swift b/Tests/web3swiftTests/remoteTests/InfuraTests.swift index e2c7c5cca..870cd6ea5 100755 --- a/Tests/web3swiftTests/remoteTests/InfuraTests.swift +++ b/Tests/web3swiftTests/remoteTests/InfuraTests.swift @@ -25,20 +25,20 @@ class InfuraTests: XCTestCase { func testGetBlockByHash() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByHash("0x6d05ba24da6b7a1af22dc6cc2a1fe42f58b2a5ea4c406b19c8cf672ed8ec0695", fullTransactions: false) + let result = try await web3.eth.block(by: "0x6d05ba24da6b7a1af22dc6cc2a1fe42f58b2a5ea4c406b19c8cf672ed8ec0695", fullTransactions: false) print(result) } func testGetBlockByNumber1() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByNumber(.latest, fullTransactions: false) + let result = try await web3.eth.block(by: .latest, fullTransactions: false) print(result) } func testGetBlockByNumber2() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let result = try await web3.eth.getBlockByNumber(.exact(5184323), fullTransactions: true) + let result = try await web3.eth.block(by: .exact(5184323), fullTransactions: true) print(result) let transactions = result.transactions for transaction in transactions { @@ -54,7 +54,7 @@ class InfuraTests: XCTestCase { func testGetBlockByNumber3() async throws { do { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let _ = try await web3.eth.getBlockByNumber(.exact(1000000000), fullTransactions: true) + let _ = try await web3.eth.block(by: .exact(1000000000), fullTransactions: true) XCTFail() } catch { @@ -63,7 +63,7 @@ class InfuraTests: XCTestCase { func testGasPrice() async throws { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) - let response = try await web3.eth.getGasPrice() + let response = try await web3.eth.gasPrice() print(response) } From fec0bc05bca23e18542099e499375a5e4f332a58 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 1 Jun 2022 16:31:15 +0700 Subject: [PATCH 39/45] Little code formatting --- Sources/web3swift/API/APIMethod.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 14f338a10..a59cd9568 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -245,7 +245,7 @@ extension APIRequest { if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { /// This types for sure conformed with `LiteralInitiableFromString` // FIXME: Make appropriate error - guard let U = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.unknownError} + guard let U = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.unknownError } let responseAsString = try! JSONDecoder().decode(APIResponse.self, from: data) // FIXME: Add appropriate error thrown. guard let literalValue = U.init(from: responseAsString.result) else { throw Web3Error.unknownError } From 78301bdb4db5cf61f5a378eb0c7de0794adf2908 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 2 Jun 2022 16:28:10 +0700 Subject: [PATCH 40/45] Fix wrong sendTransaction request bug. --- Sources/web3swift/API/APIMethod.swift | 7 ++++--- .../EthereumAPICalls/Ethereum/Eth+SendTransaction.swift | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index a59cd9568..0d3707d77 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -25,7 +25,7 @@ public enum APIRequest { // ?? case estimateGas(TransactionParameters, BlockNumber) case sendRawTransaction(Hash) - case sendTransaction(TransactionParameters, BlockNumber) + case sendTransaction(TransactionParameters) case getTransactionByHash(Hash) case getTransactionReceipt(Hash) case getLogs(EventFilterParameters) @@ -148,8 +148,8 @@ extension APIRequest { case let .sendRawTransaction(hash): return [RequestParameter.string(hash)] - case .sendTransaction(let transactionParameters, let blockNumber): - return [RequestParameter.transaction(transactionParameters), RequestParameter.string(blockNumber.stringValue)] + case let .sendTransaction(transactionParameters): + return [RequestParameter.transaction(transactionParameters)] case .getTransactionByHash(let hash): return [RequestParameter.string(hash)] @@ -240,6 +240,7 @@ extension APIRequest { guard let httpResponse = response as? HTTPURLResponse, 200 ..< 400 ~= httpResponse.statusCode else { throw Web3Error.connectionError } + // FIXME: Add throwing an error from is server fails. /// This bit of code is purposed to work with literal types that comes in Response in hexString type. /// Currently it's just any kind of Integers like `(U)Int`, `Big(U)Int`. if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift index c8aed56ba..386fab32a 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift @@ -49,7 +49,7 @@ extension web3.Eth { // FIXME: Add appropriate error guard let transactionParameters = transaction.encodeAsDictionary(from: transactionOptions?.from) else { throw Web3Error.unknownError } - let request: APIRequest = .sendTransaction(transactionParameters, transactionOptions?.callOnBlock ?? .latest) + let request: APIRequest = .sendTransaction(transactionParameters) let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) let result = TransactionSendingResult(transaction: assembledTransaction, hash: response.result) From 41ac98fb04ddb0c648055159d65266399311843b Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 2 Jun 2022 17:19:35 +0700 Subject: [PATCH 41/45] Fix `gasLimit` and `gasPrice` request bug. Node throws and error if these parameters exist in request and lower than `21100` for formet and `10000000` for latter. --- Sources/web3swift/Transaction/EIP1559Envelope.swift | 2 +- Sources/web3swift/Transaction/EIP2930Envelope.swift | 4 ++-- Sources/web3swift/Transaction/LegacyEnvelope.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/web3swift/Transaction/EIP1559Envelope.swift b/Sources/web3swift/Transaction/EIP1559Envelope.swift index 5944dac54..0a2fc7c24 100644 --- a/Sources/web3swift/Transaction/EIP1559Envelope.swift +++ b/Sources/web3swift/Transaction/EIP1559Envelope.swift @@ -313,7 +313,7 @@ extension EIP1559Envelope { accessEncoding.append(encoded) } params.accessList = accessEncoding - let gasEncoding = self.gasLimit.abiEncode(bits: 256) + let gasEncoding = gasLimit > 21100 ? self.gasLimit.abiEncode(bits: 256) : nil params.gas = gasEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() let maxFeeEncoding = self.maxFeePerGas.abiEncode(bits: 256) params.maxFeePerGas = maxFeeEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() diff --git a/Sources/web3swift/Transaction/EIP2930Envelope.swift b/Sources/web3swift/Transaction/EIP2930Envelope.swift index 5413f3e56..5633795e7 100644 --- a/Sources/web3swift/Transaction/EIP2930Envelope.swift +++ b/Sources/web3swift/Transaction/EIP2930Envelope.swift @@ -288,9 +288,9 @@ extension EIP2930Envelope { accessEncoding.append(encoded) } params.accessList = accessEncoding - let gasEncoding = self.gasLimit.abiEncode(bits: 256) + let gasEncoding = gasLimit > 21100 ? self.gasLimit.abiEncode(bits: 256) : nil params.gas = gasEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() - let gasPriceEncoding = self.gasPrice.abiEncode(bits: 256) + let gasPriceEncoding = gasPrice > 10000000 ? self.gasPrice.abiEncode(bits: 256) : nil params.gasPrice = gasPriceEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() let valueEncoding = self.value.abiEncode(bits: 256) params.value = valueEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() diff --git a/Sources/web3swift/Transaction/LegacyEnvelope.swift b/Sources/web3swift/Transaction/LegacyEnvelope.swift index 120898d75..6628b9f3f 100644 --- a/Sources/web3swift/Transaction/LegacyEnvelope.swift +++ b/Sources/web3swift/Transaction/LegacyEnvelope.swift @@ -251,9 +251,9 @@ extension LegacyEnvelope { break } var params = TransactionParameters(from: from?.address.lowercased(), to: toString) - let gasEncoding = self.gasLimit.abiEncode(bits: 256) + let gasEncoding = gasLimit > 21100 ? self.gasLimit.abiEncode(bits: 256) : nil params.gas = gasEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() - let gasPriceEncoding = self.gasPrice.abiEncode(bits: 256) + let gasPriceEncoding = gasPrice > 10000000 ? self.gasPrice.abiEncode(bits: 256) : nil params.gasPrice = gasPriceEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() let valueEncoding = self.value.abiEncode(bits: 256) params.value = valueEncoding?.toHexString().addHexPrefix().stripLeadingZeroes() From 23ef94afbb734c55bd1cf6a82f7e3e1e6730b758 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 2 Jun 2022 23:57:02 +0700 Subject: [PATCH 42/45] Add Data type support by conforming `LiteralInitiableFromString` protocol. - Rename init of `DecodableFromHex` protocol to make it crossing with `LiteralInitiableFromString`. --- .../web3swift/API/HexDecodableProtocols.swift | 4 +++- .../Convenience/Decodable+Extensions.swift | 16 +++++++-------- .../EthereumAPICalls/Ethereum/Eth+Call.swift | 2 +- .../Transaction/EIP2930Envelope.swift | 2 +- .../localTests/EIP1559BlockTests.swift | 20 +++++++++---------- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/web3swift/API/HexDecodableProtocols.swift index 45b7ea3f8..e446e9230 100644 --- a/Sources/web3swift/API/HexDecodableProtocols.swift +++ b/Sources/web3swift/API/HexDecodableProtocols.swift @@ -6,6 +6,7 @@ // import BigInt +import Foundation public protocol APIResultType: Decodable { } @@ -37,7 +38,6 @@ extension LiteralInitiableFromString where Self: IntegerInitableWithRadix { } } - extension Int: LiteralInitiableFromString { } extension UInt: LiteralInitiableFromString { } @@ -46,6 +46,8 @@ extension BigInt: LiteralInitiableFromString { } extension BigUInt: LiteralInitiableFromString { } +extension Data: LiteralInitiableFromString { } + public protocol IntegerInitableWithRadix { init?(_ text: S, radix: Int) } diff --git a/Sources/web3swift/Convenience/Decodable+Extensions.swift b/Sources/web3swift/Convenience/Decodable+Extensions.swift index ee0c05cff..e09e27f9a 100644 --- a/Sources/web3swift/Convenience/Decodable+Extensions.swift +++ b/Sources/web3swift/Convenience/Decodable+Extensions.swift @@ -33,7 +33,7 @@ extension KeyedDecodingContainer { /// - throws: `Web3Error.dataError` if value associated with key are unable to be initialized as `DecodableFromHex`. public func decodeHex(_ type: T.Type, forKey: KeyedDecodingContainer.Key) throws -> T { let hexString = try self.decode(String.self, forKey: forKey) - guard let value = T(fromHex: hexString) else { throw Web3Error.dataError } + guard let value = T(from: hexString) else { throw Web3Error.dataError } return value } @@ -92,7 +92,7 @@ public extension UnkeyedDecodingContainer { var array: [T] = [] while !isAtEnd { let hexString = try decode(String.self) - guard let item = T(fromHex: hexString) else { continue } + guard let item = T(from: hexString) else { continue } array.append(item) } return array @@ -119,11 +119,11 @@ public extension UnkeyedDecodingContainer { } public protocol DecodableFromHex: Decodable { - init?(fromHex hexString: String) + init?(from hexString: String) } extension Data: DecodableFromHex { - public init?(fromHex hexString: String) { + public init?(from hexString: String) { self.init() guard let tmp = Self.fromHex(hexString) else { return nil } self = tmp @@ -131,19 +131,19 @@ extension Data: DecodableFromHex { } extension UInt: DecodableFromHex { - public init?(fromHex hexString: String) { + public init?(from hexString: String) { self.init(hexString.stripHexPrefix(), radix: 16) } } extension BigUInt: DecodableFromHex { - public init?(fromHex hexString: String) { + public init?(from hexString: String) { self.init(hexString.stripHexPrefix(), radix: 16) } } extension Date: DecodableFromHex { - public init?(fromHex hexString: String) { + public init?(from hexString: String) { self.init() let stripedHexString = hexString.stripHexPrefix() guard let timestampInt = UInt(stripedHexString, radix: 16) else { return nil } @@ -152,7 +152,7 @@ extension Date: DecodableFromHex { } extension EthereumAddress: DecodableFromHex { - public init?(fromHex hexString: String) { + public init?(from hexString: String) { self.init(hexString, ignoreChecksum: true) } } diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift index f38400369..13cbc0389 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift @@ -14,7 +14,7 @@ extension web3.Eth { // FIXME: Add appropriate error guard let transactionParameters = transaction.encodeAsDictionary(from: transactionOptions?.from) else { throw Web3Error.unknownError} let request: APIRequest = .call(transactionParameters, transactionOptions?.callOnBlock ?? .latest) - let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) + let response: APIResponse = try await APIRequest.sendRequest(with: self.provider, for: request) return response.result } } diff --git a/Sources/web3swift/Transaction/EIP2930Envelope.swift b/Sources/web3swift/Transaction/EIP2930Envelope.swift index 5633795e7..7d9eaa5df 100644 --- a/Sources/web3swift/Transaction/EIP2930Envelope.swift +++ b/Sources/web3swift/Transaction/EIP2930Envelope.swift @@ -333,7 +333,7 @@ public struct AccessListEntry: CustomStringConvertible, Decodable { self.storageKeys = [] if let keyStrings = try? container.decode([String].self, forKey: .storageKeys) { for keyString in keyStrings { - guard let number = BigUInt(fromHex: keyString) else { throw Web3Error.dataError } + guard let number = BigUInt(from: keyString) else { throw Web3Error.dataError } self.storageKeys.append(number) } } diff --git a/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift b/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift index e60ef23b9..b56a40f42 100644 --- a/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift +++ b/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift @@ -7,19 +7,19 @@ import web3swift class EIP1559BlockTests: LocalTestCase { let uselessBlockPart = ( number: BigUInt(12_965_000), - hash: Data(fromHex: "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46")!, // "hash": - parentHash: Data(fromHex: "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88")!, // "parentHash": - nonce: Data(fromHex: "0xfb6e1a62d119228b"), // "nonce": - sha3Uncles: Data(fromHex: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "sha3Uncles": - receiptsRoot: Data(fromHex: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "receiptsRoot": - logsBloom: EthereumBloomFilter(Data(fromHex: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")!), // "logsBloom": - transactionsRoot: Data(fromHex: "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee")!, // "transactionsRoot": - stateRoot: Data(fromHex: "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb")!, // "stateRoot": - miner: EthereumAddress( Data(fromHex: "0x8888f1f195afa192cfee860698584c030f4c9db1")!)!, // "miner": + hash: Data(from: "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46")!, // "hash": + parentHash: Data(from: "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88")!, // "parentHash": + nonce: Data(from: "0xfb6e1a62d119228b"), // "nonce": + sha3Uncles: Data(from: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "sha3Uncles": + receiptsRoot: Data(from: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")!, // "receiptsRoot": + logsBloom: EthereumBloomFilter(Data(from: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")!), // "logsBloom": + transactionsRoot: Data(from: "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee")!, // "transactionsRoot": + stateRoot: Data(from: "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb")!, // "stateRoot": + miner: EthereumAddress( Data(from: "0x8888f1f195afa192cfee860698584c030f4c9db1")!)!, // "miner": difficulty: BigUInt(21345678965432), // "difficulty": totalDifficulty: BigUInt(324567845321), // "totalDifficulty": size: BigUInt(616), // "size": - extraData: Data(fromHex: "0x")!, // extraData": + extraData: Data(from: "0x")!, // extraData": gasLimit: BigUInt(3141592), // "gasLimit": gasUsed: BigUInt(21662), // "gasUsed": timestamp: Date(), // "timestamp": From fa80d437b32999c2d6ec4e621905441e65ba093a Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 3 Jun 2022 08:42:34 +0700 Subject: [PATCH 43/45] Implement `GetLogs` call. Now all tests are green. --- Sources/web3swift/API/APIMethod.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 0d3707d77..4b5897b4d 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -122,9 +122,9 @@ extension APIRequest { case .personalSign: return Data.self case .getTxPoolStatus: return TxPoolStatus.self case .getTxPoolContent: return TxPoolContent.self + case .getLogs: return [EventLog].self // FIXME: Not implemented - case .getLogs: return String.self case .getStorageAt: return String.self case .getTxPoolInspect: return String.self } From 90e206183da08358b9f121a83d405aacbb7ba6cc Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Mon, 6 Jun 2022 01:26:19 +0700 Subject: [PATCH 44/45] Update Web3HTTPProvider - Drop methods `sendRequest` from Web3Provider protocol. - Move out network request code from `Web3HTTPProvider`. - Network enum are now inits from UInt instead of Int. Fixed bug of not decoding Data responses. --- Sources/web3swift/API/APIMethod.swift | 27 +++--- .../API/Async+BackwardCapability.swift | 40 +++++++++ Sources/web3swift/Utils/EIP/EIP681.swift | 2 +- .../web3swift/Web3/Web3+HttpProvider.swift | 88 ++++--------------- Sources/web3swift/Web3/Web3+Protocols.swift | 2 +- 5 files changed, 73 insertions(+), 86 deletions(-) create mode 100644 Sources/web3swift/API/Async+BackwardCapability.swift diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/web3swift/API/APIMethod.swift index 4b5897b4d..e1f99723c 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/web3swift/API/APIMethod.swift @@ -232,9 +232,21 @@ extension APIRequest { /// Don't even try to make network request if the `Result` type dosen't equal to supposed by API // FIXME: Add appropriate error thrown guard Result.self == call.responseType else { throw Web3Error.unknownError } - let request = setupRequest(for: call, with: provider) - let (data, response) = try await provider.session.data(for: request) + return try await APIRequest.send(uRLRequest: request, with: provider.session) + } + + static func setupRequest(for call: APIRequest, with provider: Web3Provider) -> URLRequest { + var urlRequest = URLRequest(url: provider.url, cachePolicy: .reloadIgnoringCacheData) + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") + urlRequest.httpMethod = call.method.rawValue + urlRequest.httpBody = call.encodedBody + return urlRequest + } + + static func send(uRLRequest: URLRequest, with session: URLSession) async throws -> APIResponse { + let (data, response) = try await session.data(for: uRLRequest) // FIXME: Add appropriate error thrown guard let httpResponse = response as? HTTPURLResponse, @@ -243,7 +255,7 @@ extension APIRequest { // FIXME: Add throwing an error from is server fails. /// This bit of code is purposed to work with literal types that comes in Response in hexString type. /// Currently it's just any kind of Integers like `(U)Int`, `Big(U)Int`. - if Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { + if Result.self == Data.self || Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { /// This types for sure conformed with `LiteralInitiableFromString` // FIXME: Make appropriate error guard let U = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.unknownError } @@ -257,15 +269,6 @@ extension APIRequest { } return try JSONDecoder().decode(APIResponse.self, from: data) } - - static func setupRequest(for call: APIRequest, with provider: Web3Provider) -> URLRequest { - var urlRequest = URLRequest(url: provider.url, cachePolicy: .reloadIgnoringCacheData) - urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") - urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") - urlRequest.httpMethod = call.method.rawValue - urlRequest.httpBody = call.encodedBody - return urlRequest - } } enum REST: String { diff --git a/Sources/web3swift/API/Async+BackwardCapability.swift b/Sources/web3swift/API/Async+BackwardCapability.swift new file mode 100644 index 000000000..e6286be2c --- /dev/null +++ b/Sources/web3swift/API/Async+BackwardCapability.swift @@ -0,0 +1,40 @@ +// +// Async+BackwardCapability.swift +// +// +// Created by Yaroslav Yashin on 05.06.2022. +// + +import Foundation + +@available(iOS, obsoleted: 15.0, message: "Use the built-in API instead") +@available(macOS, obsoleted: 12.0, message: "Use the built-in API instead") +extension URLSession { + func data(fromUrl url: URL) async throws -> (Data, URLResponse) { + try await withCheckedThrowingContinuation { continuation in + let task = self.dataTask(with: url) { data, response, error in + guard let data = data, let response = response else { + let error = error ?? URLError(.badServerResponse) + return continuation.resume(throwing: error) + } + continuation.resume(returning: (data, response)) + } + task.resume() + } + } + + func data(for request: URLRequest) async throws -> (Data, URLResponse) { + var dataTask: URLSessionDataTask? + + return try await withCheckedThrowingContinuation { continuation in + dataTask = self.dataTask(with: request) { data, response, error in + guard let data = data, let response = response else { + let error = error ?? URLError(.badServerResponse) + return continuation.resume(throwing: error) + } + continuation.resume(returning: (data, response)) + } + dataTask?.resume() + } + } +} diff --git a/Sources/web3swift/Utils/EIP/EIP681.swift b/Sources/web3swift/Utils/EIP/EIP681.swift index 443eacbbd..5c8d47264 100755 --- a/Sources/web3swift/Utils/EIP/EIP681.swift +++ b/Sources/web3swift/Utils/EIP/EIP681.swift @@ -122,7 +122,7 @@ extension Web3 { // return nil case .ensAddress(let ens): do { - let web = await web3(provider: InfuraProvider(Networks.fromInt(Int(code.chainID ?? 1)) ?? Networks.Mainnet)!) + let web = await web3(provider: InfuraProvider(Networks.fromInt(UInt(code.chainID ?? 1)) ?? Networks.Mainnet)!) let ensModel = ENS(web3: web) try await ensModel?.setENSResolver(withDomain: ens) let address = try await ensModel?.getAddress(forNode: ens) diff --git a/Sources/web3swift/Web3/Web3+HttpProvider.swift b/Sources/web3swift/Web3/Web3+HttpProvider.swift index dfc52bc5b..dd662071f 100755 --- a/Sources/web3swift/Web3/Web3+HttpProvider.swift +++ b/Sources/web3swift/Web3/Web3+HttpProvider.swift @@ -10,8 +10,6 @@ import BigInt /// Providers abstraction for custom providers (websockets, other custom private key managers). At the moment should not be used. public protocol Web3Provider { -// func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse -// func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch var network: Networks? {get set} var attachedKeystoreManager: KeystoreManager? {get set} var url: URL {get} @@ -28,79 +26,25 @@ public class Web3HttpProvider: Web3Provider { let urlSession = URLSession(configuration: config) return urlSession }() - public init?(_ httpProviderURL: URL, network net: Networks, keystoreManager manager: KeystoreManager? = nil) { + public init?(_ httpProviderURL: URL, network net: Networks?, keystoreManager manager: KeystoreManager? = nil) async { guard httpProviderURL.scheme == "http" || httpProviderURL.scheme == "https" else { return nil } url = httpProviderURL - network = net - attachedKeystoreManager = manager - } - -// fileprivate static func dataFrom(session: URLSession, request urlRequest: URLRequest) async throws -> Data{ -// let (data, _) = try await session.data(for: urlRequest) -// return data -// } -// -// static func post(_ request: U, providerURL: URL, session: URLSession) async throws -> T { -// let requestData = try JSONEncoder().encode(request) -// var urlRequest = URLRequest(url: providerURL, cachePolicy: .reloadIgnoringCacheData) -// urlRequest.httpMethod = "POST" -// urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") -// urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") -// urlRequest.httpBody = requestData -// -// let data = try await dataFrom(session: session, request: urlRequest) -// -// let parsedResponse = try JSONDecoder().decode(T.self, from: data) -// -// if let response = parsedResponse as? JSONRPCresponse, response.error != nil { -// throw Web3Error.nodeError(desc: "Received an error message from node\n" + String(describing: response.error!)) -// } -// return parsedResponse -// -// } -// -// public func sendAsync(_ request: JSONRPCrequest) async throws -> JSONRPCresponse { -// guard request.method != nil else { -// throw Web3Error.nodeError(desc: "RPC method is nill") -// } -// -// return try await Web3HttpProvider.post(request, providerURL: self.url, session: self.session) -// } - -// public func sendAsync(_ requests: JSONRPCrequestBatch) async throws -> JSONRPCresponseBatch { -// return try await Web3HttpProvider.post(requests, providerURL: self.url, session: self.session) -// } -} - - -@available(iOS, obsoleted: 15.0, message: "Use the built-in API instead") -@available(macOS, obsoleted: 12.0, message: "Use the built-in API instead") -extension URLSession { - func data(fromUrl url: URL) async throws -> (Data, URLResponse) { - try await withCheckedThrowingContinuation { continuation in - let task = self.dataTask(with: url) { data, response, error in - guard let data = data, let response = response else { - let error = error ?? URLError(.badServerResponse) - return continuation.resume(throwing: error) - } - continuation.resume(returning: (data, response)) - } - task.resume() - } - } - - func data(for request: URLRequest) async throws -> (Data, URLResponse) { - var dataTask: URLSessionDataTask? - - return try await withCheckedThrowingContinuation { continuation in - dataTask = self.dataTask(with: request) { data, response, error in - guard let data = data, let response = response else { - let error = error ?? URLError(.badServerResponse) - return continuation.resume(throwing: error) - } - continuation.resume(returning: (data, response)) + if let net = net { + network = net + } else { + var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData) + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + urlRequest.setValue("application/json", forHTTPHeaderField: "Accept") + urlRequest.httpMethod = APIRequest.getNetwork.call + urlRequest.httpBody = APIRequest.getNetwork.encodedBody + do { + let response: APIResponse = try await APIRequest.send(uRLRequest: urlRequest, with: session) + let network = Networks.fromInt(response.result) + self.network = network + } catch { + return nil } - dataTask?.resume() } + attachedKeystoreManager = manager } } diff --git a/Sources/web3swift/Web3/Web3+Protocols.swift b/Sources/web3swift/Web3/Web3+Protocols.swift index 017e8843e..c265e74ca 100755 --- a/Sources/web3swift/Web3/Web3+Protocols.swift +++ b/Sources/web3swift/Web3/Web3+Protocols.swift @@ -58,7 +58,7 @@ public enum Networks { static let allValues = [Mainnet, Ropsten, Kovan, Rinkeby] - static func fromInt(_ networkID: Int) -> Networks? { + static func fromInt(_ networkID: UInt) -> Networks? { switch networkID { case 1: return Networks.Mainnet From 55732abd04fab9437b6431fe48876ae016971d18 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 8 Jun 2022 22:40:42 +0700 Subject: [PATCH 45/45] Delete unused `URLSession.data` method method. --- .../web3swift/API/Async+BackwardCapability.swift | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Sources/web3swift/API/Async+BackwardCapability.swift b/Sources/web3swift/API/Async+BackwardCapability.swift index e6286be2c..47eb86898 100644 --- a/Sources/web3swift/API/Async+BackwardCapability.swift +++ b/Sources/web3swift/API/Async+BackwardCapability.swift @@ -10,19 +10,6 @@ import Foundation @available(iOS, obsoleted: 15.0, message: "Use the built-in API instead") @available(macOS, obsoleted: 12.0, message: "Use the built-in API instead") extension URLSession { - func data(fromUrl url: URL) async throws -> (Data, URLResponse) { - try await withCheckedThrowingContinuation { continuation in - let task = self.dataTask(with: url) { data, response, error in - guard let data = data, let response = response else { - let error = error ?? URLError(.badServerResponse) - return continuation.resume(throwing: error) - } - continuation.resume(returning: (data, response)) - } - task.resume() - } - } - func data(for request: URLRequest) async throws -> (Data, URLResponse) { var dataTask: URLSessionDataTask?