diff --git a/Package.swift b/Package.swift index 252f7a7f7..c6245fcc4 100755 --- a/Package.swift +++ b/Package.swift @@ -19,7 +19,6 @@ let package = Package( products: [ .library(name: "web3swift", targets: ["web3swift"]) ], - dependencies: [ .package(url: "https://github.com/attaswift/BigInt.git", from: "5.3.0"), .package(url: "https://github.com/daltoniam/Starscream.git", from: "4.0.4"), @@ -27,9 +26,13 @@ let package = Package( ], targets: [ .target(name: "secp256k1"), + .target( + name: "Core", + dependencies: ["BigInt", "secp256k1", "CryptoSwift"] + ), .target( name: "web3swift", - dependencies: ["BigInt", "secp256k1", "Starscream", "CryptoSwift"], + dependencies: ["Core", "BigInt", "secp256k1", "Starscream"], exclude: excludeFiles, resources: [ .copy("./Browser/browser.js"), diff --git a/Sources/web3swift/EthereumAddress/EthereumAddress.swift b/Sources/Core/EthereumAddress/EthereumAddress.swift similarity index 90% rename from Sources/web3swift/EthereumAddress/EthereumAddress.swift rename to Sources/Core/EthereumAddress/EthereumAddress.swift index 1ad1c8013..aea8302c6 100755 --- a/Sources/web3swift/EthereumAddress/EthereumAddress.swift +++ b/Sources/Core/EthereumAddress/EthereumAddress.swift @@ -124,6 +124,20 @@ extension EthereumAddress { } +extension EthereumAddress: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let stringValue = try container.decode(String.self) + self.init(stringValue)! + } + + public func encode(to encoder: Encoder) throws { + let value = self.address.lowercased() + var signleValuedCont = encoder.singleValueContainer() + try signleValuedCont.encode(value) + } +} + extension EthereumAddress: Hashable { } extension EthereumAddress: APIResultType { } diff --git a/Sources/Core/EthereumNetwork/Request/APIRequest+ComputedProperties.swift b/Sources/Core/EthereumNetwork/Request/APIRequest+ComputedProperties.swift new file mode 100644 index 000000000..36cb9dad5 --- /dev/null +++ b/Sources/Core/EthereumNetwork/Request/APIRequest+ComputedProperties.swift @@ -0,0 +1,111 @@ +// +// APIRequest+ComputedProperties.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +extension APIRequest { + var method: REST { + switch self { + default: return .POST + } + } + + public var encodedBody: Data { + 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) + } + + var parameters: [RequestParameter] { + switch self { + case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .getTxPoolStatus, .getTxPoolContent, .getTxPoolInspect: + return [RequestParameter]() + + case .estimateGas(let transactionParameters, let blockNumber): + return [.transaction(transactionParameters), .string(blockNumber.stringValue)] + + case let .sendRawTransaction(hash): + return [.string(hash)] + + case let .sendTransaction(transactionParameters): + return [.transaction(transactionParameters)] + + case .getTransactionByHash(let hash): + return [.string(hash)] + + case .getTransactionReceipt(let receipt): + return [.string(receipt)] + + case .getLogs(let eventFilterParameters): + return [.eventFilter(eventFilterParameters)] + + case .personalSign(let address, let string): + return [.string(address), .string(string)] + + case .call(let transactionParameters, let blockNumber): + return [.transaction(transactionParameters), .string(blockNumber.stringValue)] + + case .getTransactionCount(let address, let blockNumber): + return [.string(address), .string(blockNumber.stringValue)] + + case .getBalance(let address, let blockNumber): + return [.string(address), .string(blockNumber.stringValue)] + + case .getStorageAt(let address, let bigUInt, let blockNumber): + return [.string(address), .string(bigUInt.hexString), .string(blockNumber.stringValue)] + + case .getCode(let address, let blockNumber): + return [.string(address), .string(blockNumber.stringValue)] + + case .getBlockByHash(let hash, let bool): + return [.string(hash), .bool(bool)] + + case .getBlockByNumber(let block, let bool): + return [.string(block.stringValue), .bool(bool)] + + case .feeHistory(let uInt, let blockNumber, let array): + return [.string(uInt.hexString), .string(blockNumber.stringValue), .doubleArray(array)] + + case .createAccount(let string): + return [.string(string)] + + case .unlockAccount(let address, let string, let uInt): + return [.string(address), .string(string), .uint(uInt ?? 0)] + } + } + + public 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" + } + } +} diff --git a/Sources/Core/EthereumNetwork/Request/APIRequest+Methods.swift b/Sources/Core/EthereumNetwork/Request/APIRequest+Methods.swift new file mode 100644 index 000000000..6ee4553f5 --- /dev/null +++ b/Sources/Core/EthereumNetwork/Request/APIRequest+Methods.swift @@ -0,0 +1,49 @@ +// +// APIRequest+Methods.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +extension APIRequest { + public static func sendRequest(with provider: Web3Provider, for call: APIRequest) async throws -> APIResponse { + let request = setupRequest(for: call, with: provider) + 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 + } + + public static func send(uRLRequest: URLRequest, with session: URLSession) async throws -> APIResponse { + let (data, response) = try await session.data(for: uRLRequest) + + guard 200 ..< 400 ~= response.statusCode else { + if 400 ..< 500 ~= response.statusCode { + throw Web3Error.clientError(code: response.statusCode) + } else { + throw Web3Error.serverError(code: response.statusCode) + } + } + + /// This bit of code is purposed to work with literal types that comes in Response in hexString type. + /// Currently it's just `Data` and any kind of Integers `(U)Int`, `Big(U)Int`. + if Result.self == Data.self || Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { + guard let LiteralType = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.typeError } + guard let responseAsString = try? JSONDecoder().decode(APIResponse.self, from: data) else { throw Web3Error.dataError } + guard let literalValue = LiteralType.init(from: responseAsString.result) else { throw Web3Error.dataError } + /// `Literal` conforming `LiteralInitiableFromString`, that conforming to an `APIResponseType` type, so it's never fails. + guard let result = literalValue as? Result else { throw Web3Error.typeError } + return APIResponse(id: responseAsString.id, jsonrpc: responseAsString.jsonrpc, result: result) + } + return try JSONDecoder().decode(APIResponse.self, from: data) + } +} diff --git a/Sources/Core/EthereumNetwork/Request/APIRequest+UtilityTypes.swift b/Sources/Core/EthereumNetwork/Request/APIRequest+UtilityTypes.swift new file mode 100644 index 000000000..6c54fb887 --- /dev/null +++ b/Sources/Core/EthereumNetwork/Request/APIRequest+UtilityTypes.swift @@ -0,0 +1,28 @@ +// +// APIRequest+UtilityTypes.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +/// JSON RPC response structure for serialization and deserialization purposes. +public struct APIResponse: Decodable where Result: APIResultType { + public var id: Int + public var jsonrpc = "2.0" + public var result: Result +} + +enum REST: String { + case POST + case GET +} + +struct RequestBody: Encodable { + var jsonrpc = "2.0" + var id = Counter.increment() + + var method: String + var params: [RequestParameter] +} diff --git a/Sources/web3swift/API/APIMethod.swift b/Sources/Core/EthereumNetwork/Request/APIRequest.swift similarity index 57% rename from Sources/web3swift/API/APIMethod.swift rename to Sources/Core/EthereumNetwork/Request/APIRequest.swift index 62437fa27..f8a1fcb6d 100644 --- a/Sources/web3swift/API/APIMethod.swift +++ b/Sources/Core/EthereumNetwork/Request/APIRequest.swift @@ -1,5 +1,5 @@ // -// Web3+APIMethod.swift +// APIRequest.swift // Web3swift // // Created by Yaroslav on 24.05.2022. @@ -67,14 +67,20 @@ public typealias TransactionHash = Hash // 64 chars length without 0x /// This protocol is just utility one, which declares some convenient initializer which have both `Int` and `BigInt` types, but don’t have any common protocol which declares such requirement. /// /// ### Utility types -/// - `struct RequestBody: Encodable` — just a request body that passes into request body. -/// - `public enum REST: String` — enum of REST methods. Only `POST` and `GET` presented yet. -/// - `enum RequestParameter` — this enum is a request composing helper. It make happened to encode request attribute as heterogeneous array. -/// - `protocol APIRequestParameterType: Encodable` — this type is part of the ``RequestParameter`` enum mechanism which purpose is to restrict types that can be passed as associated types within `RequestParameter` cases. -/// - `protocol APIRequestParameterElementType: Encodable` — this type purpose is the same as ``APIRequestParameterType` one except this one is made for `Element`s of an `Array` s when the latter is an associated type of a given `RequestParameter` case. +/// - `struct RequestBody: Encodable` — just a request body that passes into request body. +/// - `public enum REST: String` — enum of REST methods. Only `POST` and `GET` presented yet. +/// - `enum RequestParameter` — this enum is a request composing helper. It make happened to encode request attribute as heterogeneous array. +/// - `protocol APIRequestParameterType: Encodable` — this type is part of the ``RequestParameter`` enum mechanism which purpose is to restrict types that can be passed as associated types within `RequestParameter` cases. +/// - `protocol APIRequestParameterElementType: Encodable` — this type purpose is the same as ``APIRequestParameterType` one except this one is made for `Element`s of an `Array` s when the latter is an associated type of a given `RequestParameter` case. +/// +/// ## Supported Namespaces +/// - eth Namespace - https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods +/// - personal Namespace - https://geth.ethereum.org/docs/rpc/ns-personal +/// - tx Namespace - https://geth.ethereum.org/docs/rpc/ns-txpool public enum APIRequest { // MARK: - Official Ethereum API - + // eth Namespace - https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods + /// Gas price request case gasPrice @@ -188,7 +194,8 @@ public enum APIRequest { /// by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed." case feeHistory(BigUInt, BlockNumber, [Double]) - // MARK: - Additional Ethereum API + // MARK: - Personal Ethereum API + // personal Namespace - https://geth.ethereum.org/docs/rpc/ns-personal /// Creates new account. /// @@ -212,164 +219,10 @@ public enum APIRequest { /// - String: Passphrase to unlock the account. /// - UInt?: Duration in seconds how long the account should remain unlocked for. case unlockAccount(Address, String, UInt?) + + // MARK: - Tx Ethereum API + // tx Namespace - https://geth.ethereum.org/docs/rpc/ns-txpool case getTxPoolStatus // No in Eth API case getTxPoolContent // No in Eth API case getTxPoolInspect // No in Eth API } - -extension APIRequest { - var method: REST { - switch self { - default: return .POST - } - } - - var encodedBody: Data { - 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) - } - - var parameters: [RequestParameter] { - switch self { - case .gasPrice, .blockNumber, .getNetwork, .getAccounts, .getTxPoolStatus, .getTxPoolContent, .getTxPoolInspect: - 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 let .sendTransaction(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 string): - return [RequestParameter.string(address), RequestParameter.string(string)] - - 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)] - - case .getBalance(let address, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(blockNumber.stringValue)] - - case .getStorageAt(let address, let bigUInt, let blockNumber): - return [RequestParameter.string(address), RequestParameter.string(bigUInt.hexString), 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 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.string(string)] - - case .unlockAccount(let address, let string, let uInt): - return [RequestParameter.string(address), RequestParameter.string(string), RequestParameter.uint(uInt ?? 0)] - } - } - - 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 provider: Web3Provider, for call: APIRequest) async throws -> APIResponse { - let request = setupRequest(for: call, with: provider) - 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) - - guard 200 ..< 400 ~= response.statusCode else { throw Web3Error.serverError(code: response.statusCode) } - - /// This bit of code is purposed to work with literal types that comes in Response in hexString type. - /// Currently it's just `Data` and any kind of Integers `(U)Int`, `Big(U)Int`. - if Result.self == Data.self || Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self { - guard let Literal = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.typeError } - guard let responseAsString = try? JSONDecoder().decode(APIResponse.self, from: data) else { throw Web3Error.dataError } - guard let literalValue = Literal.init(from: responseAsString.result) else { throw Web3Error.dataError } - /// `Literal` conforming `LiteralInitiableFromString`, that conforming to an `APIResponseType` type, so it's never fails. - guard let result = literalValue as? Result else { throw Web3Error.typeError } - return APIResponse(id: responseAsString.id, jsonrpc: responseAsString.jsonrpc, result: result) - } - return try JSONDecoder().decode(APIResponse.self, from: data) - } -} - -enum REST: String { - case POST - case GET -} - -struct RequestBody: Encodable { - var jsonrpc = "2.0" - var id = Counter.increment() - - var method: String - var params: [RequestParameter] -} - -/// JSON RPC response structure for serialization and deserialization purposes. -public struct APIResponse: Decodable where Result: APIResultType { - public var id: Int - public var jsonrpc = "2.0" - public var result: Result -} diff --git a/Sources/Core/EthereumNetwork/RequestParameter/APIRequestParameterType.swift b/Sources/Core/EthereumNetwork/RequestParameter/APIRequestParameterType.swift new file mode 100644 index 000000000..8ec225849 --- /dev/null +++ b/Sources/Core/EthereumNetwork/RequestParameter/APIRequestParameterType.swift @@ -0,0 +1,28 @@ +// +// APIRequestParameter.swift +// +// +// Created by Yaroslav on 24.05.2022. +// + +import Foundation + +/// 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 `RequestParameter`s belongs on hardcoded supported types. +/// +/// Please see `RequestParameter` documentation for more details. +protocol APIRequestParameterType: Encodable { } + +extension Int: APIRequestParameterType { } + +extension UInt: APIRequestParameterType { } + +extension Double: APIRequestParameterType { } + +extension String: APIRequestParameterType { } + +extension Bool: APIRequestParameterType { } + +extension Array: APIRequestParameterType where Element: APIRequestParameterType { } diff --git a/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter+Encodable.swift b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter+Encodable.swift new file mode 100644 index 000000000..e60b25a34 --- /dev/null +++ b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter+Encodable.swift @@ -0,0 +1,55 @@ +// +// RequestParameter+Encodable.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +extension RequestParameter: Encodable { + /** + This encoder encodes `RequestParameter` assotiated value ignoring self value + + This is required to encode mixed types array, like + + ```swift + let someArray: [RequestParameter] = [ + .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]]` + ``` + */ + 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 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]) + + 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 [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/Core/EthereumNetwork/RequestParameter/RequestParameter+RawRepresentable.swift b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter+RawRepresentable.swift new file mode 100644 index 000000000..be166aec7 --- /dev/null +++ b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter+RawRepresentable.swift @@ -0,0 +1,70 @@ +// +// RequestParameter+RawRepresentable.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +extension RequestParameter: RawRepresentable { + /** + This init is required by ``RawRepresentable`` protocol, which is required to encode mixed type values array in JSON. + + This protocol is used to implement custom `encode` method for that enum, + which encodes an array of self-assosiated values. + + You're totally free to use explicit and more convenience member init as `RequestParameter.int(12)` in your code. + */ + 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 + + switch type(of: rawValue) { + case is Int.Type: self = .int(rawValue as! Int) + case is [Int].Type: self = .intArray(rawValue as! [Int]) + + 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]) + + 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 [Bool].Type: self = .boolArray(rawValue as! [Bool]) + + case is [EthereumTransaction].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. + var rawValue: APIRequestParameterType { + // cases can't be merged, coz it causes compile error since it couldn't predict exact type that 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 .boolArray(value): return value + + case let .transaction(value): return value + case let .eventFilter(value): return value + } + } +} diff --git a/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter.swift b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter.swift new file mode 100644 index 000000000..aeea25b26 --- /dev/null +++ b/Sources/Core/EthereumNetwork/RequestParameter/RequestParameter.swift @@ -0,0 +1,55 @@ +// +// RequestParameter.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +/** + 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]`. + + 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. + + This protocol allows the designated type to represent itself in `String` representation. + + So in our case we're using it to implement custom `encode` method for all possible types used as request params. + + This `encode` method 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: [APIRequestParameterType] = [ + .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]]` + ``` + */ +enum RequestParameter { + case int(Int) + case intArray([Int]) + + case uint(UInt) + case uintArray([UInt]) + + case double(Double) + case doubleArray([Double]) + + case string(String) + case stringArray([String]) + + case bool(Bool) + case boolArray([Bool]) + + case transaction(TransactionParameters) + case eventFilter(EventFilterParameters) +} \ No newline at end of file diff --git a/Sources/web3swift/API/Async+BackwardCapability.swift b/Sources/Core/EthereumNetwork/Utility/Async+BackwardCapability.swift similarity index 100% rename from Sources/web3swift/API/Async+BackwardCapability.swift rename to Sources/Core/EthereumNetwork/Utility/Async+BackwardCapability.swift diff --git a/Sources/Core/EthereumNetwork/Utility/HexDecodable+Extensions.swift b/Sources/Core/EthereumNetwork/Utility/HexDecodable+Extensions.swift new file mode 100644 index 000000000..31b78578f --- /dev/null +++ b/Sources/Core/EthereumNetwork/Utility/HexDecodable+Extensions.swift @@ -0,0 +1,32 @@ +// +// HexDecodable+Extensions.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +extension Int: LiteralInitiableFromString { } + +extension UInt: LiteralInitiableFromString { } + +extension BigInt: LiteralInitiableFromString { } + +extension BigUInt: LiteralInitiableFromString { } + +extension Data: LiteralInitiableFromString { + public static func fromHex(_ hex: String) -> Data? { + let string = hex.lowercased().stripHexPrefix() + let array = Array(hex: string) + if (array.count == 0) { + if (hex == "0x" || hex == "") { + return Data() + } else { + return nil + } + } + return Data(array) + } +} diff --git a/Sources/web3swift/API/HexDecodableProtocols.swift b/Sources/Core/EthereumNetwork/Utility/HexDecodableProtocols.swift similarity index 70% rename from Sources/web3swift/API/HexDecodableProtocols.swift rename to Sources/Core/EthereumNetwork/Utility/HexDecodableProtocols.swift index e446e9230..b2472448a 100644 --- a/Sources/web3swift/API/HexDecodableProtocols.swift +++ b/Sources/Core/EthereumNetwork/Utility/HexDecodableProtocols.swift @@ -14,8 +14,6 @@ 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. @@ -37,25 +35,3 @@ extension LiteralInitiableFromString where Self: IntegerInitableWithRadix { self = value } } - -extension Int: LiteralInitiableFromString { } - -extension UInt: LiteralInitiableFromString { } - -extension BigInt: LiteralInitiableFromString { } - -extension BigUInt: LiteralInitiableFromString { } - -extension Data: LiteralInitiableFromString { } - -public protocol IntegerInitableWithRadix { - init?(_ text: S, radix: Int) -} - -extension Int: IntegerInitableWithRadix { } - -extension UInt: IntegerInitableWithRadix { } - -extension BigInt: IntegerInitableWithRadix { } - -extension BigUInt: IntegerInitableWithRadix { } diff --git a/Sources/Core/EthereumNetwork/Utility/IntegerInitableWithRadix.swift b/Sources/Core/EthereumNetwork/Utility/IntegerInitableWithRadix.swift new file mode 100644 index 000000000..c02e14650 --- /dev/null +++ b/Sources/Core/EthereumNetwork/Utility/IntegerInitableWithRadix.swift @@ -0,0 +1,21 @@ +// +// IntegerInitableWithRadix.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +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/KeystoreManager/AbstractKeystore.swift b/Sources/Core/KeystoreManager/AbstractKeystore.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/AbstractKeystore.swift rename to Sources/Core/KeystoreManager/AbstractKeystore.swift diff --git a/Sources/web3swift/KeystoreManager/BIP32HDNode.swift b/Sources/Core/KeystoreManager/BIP32HDNode.swift similarity index 99% rename from Sources/web3swift/KeystoreManager/BIP32HDNode.swift rename to Sources/Core/KeystoreManager/BIP32HDNode.swift index e0011ab10..cc2ff737e 100755 --- a/Sources/web3swift/KeystoreManager/BIP32HDNode.swift +++ b/Sources/Core/KeystoreManager/BIP32HDNode.swift @@ -82,7 +82,7 @@ public class HDNode { chaincode = data[13..<45] if serializePrivate { privateKey = data[46..<78] - guard let pubKey = Web3.Utils.privateToPublic(privateKey!, compressed: true) else {return nil} + guard let pubKey = Utilities.privateToPublic(privateKey!, compressed: true) else {return nil} if pubKey[0] != 0x02 && pubKey[0] != 0x03 {return nil} publicKey = pubKey } else { diff --git a/Sources/web3swift/KeystoreManager/BIP32Keystore.swift b/Sources/Core/KeystoreManager/BIP32Keystore.swift similarity index 98% rename from Sources/web3swift/KeystoreManager/BIP32Keystore.swift rename to Sources/Core/KeystoreManager/BIP32Keystore.swift index cbe20b58e..19136d49a 100755 --- a/Sources/web3swift/KeystoreManager/BIP32Keystore.swift +++ b/Sources/Core/KeystoreManager/BIP32Keystore.swift @@ -64,7 +64,7 @@ public class BIP32Keystore: AbstractKeystore { private static let KeystoreParamsBIP32Version = 4 - private (set) var addressStorage: PathAddressStorage + public private (set) var addressStorage: PathAddressStorage public convenience init?(_ jsonString: String) { let lowercaseJSON = jsonString.lowercased() @@ -139,7 +139,7 @@ public class BIP32Keystore: AbstractKeystore { guard let newNode = parentNode.derive(index: newIndex, derivePrivateKey: true, hardened: false) else { throw AbstractKeystoreError.keyDerivationError } - guard let newAddress = Web3.Utils.publicToAddress(newNode.publicKey) else { + guard let newAddress = Utilities.publicToAddress(newNode.publicKey) else { throw AbstractKeystoreError.keyDerivationError } let prefixPath = self.rootPrefix @@ -190,7 +190,7 @@ public class BIP32Keystore: AbstractKeystore { guard let newNode = rootNode.derive(path: pathAppendix!, derivePrivateKey: true) else { throw AbstractKeystoreError.keyDerivationError } - guard let newAddress = Web3.Utils.publicToAddress(newNode.publicKey) else { + guard let newAddress = Utilities.publicToAddress(newNode.publicKey) else { throw AbstractKeystoreError.keyDerivationError } var newPath: String diff --git a/Sources/web3swift/KeystoreManager/BIP39+WordLists.swift b/Sources/Core/KeystoreManager/BIP39+WordLists.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/BIP39+WordLists.swift rename to Sources/Core/KeystoreManager/BIP39+WordLists.swift diff --git a/Sources/web3swift/KeystoreManager/BIP39.swift b/Sources/Core/KeystoreManager/BIP39.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/BIP39.swift rename to Sources/Core/KeystoreManager/BIP39.swift diff --git a/Sources/web3swift/KeystoreManager/EthereumKeystoreV3.swift b/Sources/Core/KeystoreManager/EthereumKeystoreV3.swift similarity index 98% rename from Sources/web3swift/KeystoreManager/EthereumKeystoreV3.swift rename to Sources/Core/KeystoreManager/EthereumKeystoreV3.swift index b7710e0e2..88d4b68b7 100755 --- a/Sources/web3swift/KeystoreManager/EthereumKeystoreV3.swift +++ b/Sources/Core/KeystoreManager/EthereumKeystoreV3.swift @@ -129,10 +129,10 @@ public class EthereumKeystoreV3: AbstractKeystore { let kdfparams = KdfParamsV3(salt: saltData.toHexString(), dklen: dkLen, n: N, p: P, r: R, c: nil, prf: nil) let cipherparams = CipherParamsV3(iv: IV.toHexString()) let crypto = CryptoParamsV3(ciphertext: encryptedKeyData.toHexString(), cipher: aesMode, cipherparams: cipherparams, kdf: "scrypt", kdfparams: kdfparams, mac: mac.toHexString(), version: nil) - guard let pubKey = Web3.Utils.privateToPublic(keyData!) else { + guard let pubKey = Utilities.privateToPublic(keyData!) else { throw AbstractKeystoreError.keyDerivationError } - guard let addr = Web3.Utils.publicToAddress(pubKey) else { + guard let addr = Utilities.publicToAddress(pubKey) else { throw AbstractKeystoreError.keyDerivationError } self.address = addr diff --git a/Sources/web3swift/KeystoreManager/IBAN.swift b/Sources/Core/KeystoreManager/IBAN.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/IBAN.swift rename to Sources/Core/KeystoreManager/IBAN.swift diff --git a/Sources/web3swift/KeystoreManager/KeystoreManager.swift b/Sources/Core/KeystoreManager/KeystoreManager.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/KeystoreManager.swift rename to Sources/Core/KeystoreManager/KeystoreManager.swift diff --git a/Sources/web3swift/KeystoreManager/KeystoreParams.swift b/Sources/Core/KeystoreManager/KeystoreParams.swift similarity index 100% rename from Sources/web3swift/KeystoreManager/KeystoreParams.swift rename to Sources/Core/KeystoreManager/KeystoreParams.swift diff --git a/Sources/web3swift/KeystoreManager/PathAddressStorage.swift b/Sources/Core/KeystoreManager/PathAddressStorage.swift similarity index 93% rename from Sources/web3swift/KeystoreManager/PathAddressStorage.swift rename to Sources/Core/KeystoreManager/PathAddressStorage.swift index 6c8d1b6b5..3dc747a8f 100644 --- a/Sources/web3swift/KeystoreManager/PathAddressStorage.swift +++ b/Sources/Core/KeystoreManager/PathAddressStorage.swift @@ -9,8 +9,8 @@ import Foundation public struct PathAddressStorage { - private(set) var addresses: [EthereumAddress] - private(set) var paths: [String] + public private(set) var addresses: [EthereumAddress] + public private(set) var paths: [String] init() { addresses = [] diff --git a/Sources/web3swift/KeystoreManager/PlainKeystore.swift b/Sources/Core/KeystoreManager/PlainKeystore.swift similarity index 80% rename from Sources/web3swift/KeystoreManager/PlainKeystore.swift rename to Sources/Core/KeystoreManager/PlainKeystore.swift index e62f270e6..4d85de8ef 100755 --- a/Sources/web3swift/KeystoreManager/PlainKeystore.swift +++ b/Sources/Core/KeystoreManager/PlainKeystore.swift @@ -5,6 +5,7 @@ // import Foundation +import secp256k1 public class PlainKeystore: AbstractKeystore { @@ -25,10 +26,9 @@ public class PlainKeystore: AbstractKeystore { public init?(privateKey: Data) { guard SECP256K1.verifyPrivateKey(privateKey: privateKey) else {return nil} - guard let publicKey = Web3.Utils.privateToPublic(privateKey, compressed: false) else {return nil} - guard let address = Web3.Utils.publicToAddress(publicKey) else {return nil} + guard let publicKey = Utilities.privateToPublic(privateKey, compressed: false) else {return nil} + guard let address = Utilities.publicToAddress(publicKey) else {return nil} self.addresses = [address] self.privateKey = privateKey } - } diff --git a/Sources/web3swift/SwiftRLP/RLP.swift b/Sources/Core/RLP/RLP.swift similarity index 100% rename from Sources/web3swift/SwiftRLP/RLP.swift rename to Sources/Core/RLP/RLP.swift diff --git a/Sources/web3swift/Convenience/Base58.swift b/Sources/Core/Structure/Base58.swift similarity index 100% rename from Sources/web3swift/Convenience/Base58.swift rename to Sources/Core/Structure/Base58.swift diff --git a/Sources/Core/Structure/Block/Block.swift b/Sources/Core/Structure/Block/Block.swift new file mode 100644 index 000000000..f958e3e13 --- /dev/null +++ b/Sources/Core/Structure/Block/Block.swift @@ -0,0 +1,107 @@ +// +// Block.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +/// Ethereum Block +/// +/// Official specification: [](https://github.com/ethereum/execution-apis/blob/main/src/schemas/block.json) +public struct Block: Decodable { + + public var number: BigUInt // MARK: This is optional in web3js, but required in Ethereum JSON-RPC + public var hash: Data // MARK: This is optional in web3js, but required in Ethereum JSON-RPC + public var parentHash: Data + public var nonce: Data? // MARK: This is optional in web3js but required in Ethereum JSON-RPC + public var sha3Uncles: Data + public var logsBloom: EthereumBloomFilter? = nil // MARK: This is optional in web3js but required in Ethereum JSON-RPC + public var transactionsRoot: Data + public var stateRoot: Data + public var receiptsRoot: Data + public var miner: EthereumAddress? = nil // MARK: This is NOT optional in web3js + public var difficulty: BigUInt + public var totalDifficulty: BigUInt + public var extraData: Data + public var size: BigUInt + public var gasLimit: BigUInt + public var gasUsed: BigUInt + public var baseFeePerGas: BigUInt? + public var timestamp: Date + public var transactions: [TransactionInBlock] + public var uncles: [Data] + + enum CodingKeys: String, CodingKey { + case number + case hash + case parentHash + case nonce + case sha3Uncles + case logsBloom + case transactionsRoot + case stateRoot + case receiptsRoot + case miner + case difficulty + case totalDifficulty + case extraData + case size + + case gasLimit + case gasUsed + case baseFeePerGas + + case timestamp + case transactions + case uncles + } +} + +extension Block { + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.number = try container.decodeHex(BigUInt.self, forKey: .number) + self.hash = try container.decodeHex(Data.self, forKey: .hash) + self.parentHash = try container.decodeHex(Data.self, forKey: .parentHash) + self.nonce = try? container.decodeHex(Data.self, forKey: .nonce) + self.sha3Uncles = try container.decodeHex(Data.self, forKey: .sha3Uncles) + + if let logsBloomData = try? container.decodeHex(Data.self, forKey: .logsBloom) { + self.logsBloom = EthereumBloomFilter(logsBloomData) + } + + self.transactionsRoot = try container.decodeHex(Data.self, forKey: .transactionsRoot) + self.stateRoot = try container.decodeHex(Data.self, forKey: .stateRoot) + self.receiptsRoot = try container.decodeHex(Data.self, forKey: .receiptsRoot) + + if let minerAddress = try? container.decode(String.self, forKey: .miner) { + self.miner = EthereumAddress(minerAddress) + } + + self.difficulty = try container.decodeHex(BigUInt.self, forKey: .difficulty) + self.totalDifficulty = try container.decodeHex(BigUInt.self, forKey: .totalDifficulty) + self.extraData = try container.decodeHex(Data.self, forKey: .extraData) + self.size = try container.decodeHex(BigUInt.self, forKey: .size) + self.gasLimit = try container.decodeHex(BigUInt.self, forKey: .gasLimit) + self.gasUsed = try container.decodeHex(BigUInt.self, forKey: .gasUsed) + + // optional, since pre EIP-1559 block haven't such property. + self.baseFeePerGas = try? container.decodeHex(BigUInt.self, forKey: .baseFeePerGas) + + self.timestamp = try container.decodeHex(Date.self, forKey: .timestamp) + + self.transactions = try container.decode([TransactionInBlock].self, forKey: .transactions) + + let unclesStrings = try container.decode([String].self, forKey: .uncles) + self.uncles = try unclesStrings.map { + guard let data = Data.fromHex($0) else { throw Web3Error.dataError } + return data + } + } +} + +extension Block: APIResultType { } \ No newline at end of file diff --git a/Sources/Core/Structure/Block/BlockNumber.swift b/Sources/Core/Structure/Block/BlockNumber.swift new file mode 100644 index 000000000..956a7261f --- /dev/null +++ b/Sources/Core/Structure/Block/BlockNumber.swift @@ -0,0 +1,33 @@ +// +// BlockNumber.swift +// +// +// Created by Yaroslav Yashin on 11.07.2022. +// + +import Foundation +import BigInt + +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: + return "pending" + case .latest: + return "latest" + case .earliest: + return "earliest" + case .exact(let number): + return String(number, radix: 16).addHexPrefix() + } + } +} diff --git a/Sources/web3swift/Web3/Web3+Protocols.swift b/Sources/Core/Structure/Event+Protocol.swift similarity index 78% rename from Sources/web3swift/Web3/Web3+Protocols.swift rename to Sources/Core/Structure/Event+Protocol.swift index c265e74ca..7a23222f7 100755 --- a/Sources/web3swift/Web3/Web3+Protocols.swift +++ b/Sources/Core/Structure/Event+Protocol.swift @@ -16,6 +16,23 @@ public protocol EventParserResultProtocol { var eventLog: EventLog? {get} } +public struct EventParserResult: EventParserResultProtocol { + public var eventName: String + public var transactionReceipt: TransactionReceipt? + public var contractAddress: EthereumAddress + public var decodedResult: [String: Any] + public var eventLog: EventLog? = nil + + public init(eventName: String, transactionReceipt: TransactionReceipt? = nil, contractAddress: EthereumAddress, decodedResult: [String : Any], eventLog: EventLog? = nil) { + self.eventName = eventName + self.transactionReceipt = transactionReceipt + self.contractAddress = contractAddress + self.decodedResult = decodedResult + self.eventLog = eventLog + } +} + + /// Protocol for generic Ethereum event parser public protocol EventParserProtocol { func parseTransaction(_ transaction: EthereumTransaction) async throws -> [EventParserResultProtocol] @@ -58,7 +75,7 @@ public enum Networks { static let allValues = [Mainnet, Ropsten, Kovan, Rinkeby] - static func fromInt(_ networkID: UInt) -> Networks? { + public static func fromInt(_ networkID: UInt) -> Networks? { switch networkID { case 1: return Networks.Mainnet diff --git a/Sources/Core/Structure/EventLog/EventLog.swift b/Sources/Core/Structure/EventLog/EventLog.swift new file mode 100644 index 000000000..b68052bcf --- /dev/null +++ b/Sources/Core/Structure/EventLog/EventLog.swift @@ -0,0 +1,72 @@ +import Foundation +import BigInt + +/// Represent a log, a record of some action, emitted during transaction execution. +/// +/// Example of values it can contain: +/// - `address = 0x53066cddbc0099eb6c96785d9b3df2aaeede5da3;` +/// - `blockHash = 0x779c1f08f2b5252873f08fd6ec62d75bb54f956633bbb59d33bd7c49f1a3d389;` +/// - `blockNumber = 0x4f58f8;` +/// - `data = 0x0000000000000000000000000000000000000000000000004563918244f40000;` +/// - `logIndex = 0x84;` +/// - `removed = 0;` +/// - `topics = [` +/// - `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,` +/// - `0x000000000000000000000000efdcf2c36f3756ce7247628afdb632fa4ee12ec5,` +/// - `0x000000000000000000000000d5395c132c791a7f46fa8fc27f0ab6bacd824484]` +/// - `transactionHash = 0x9f7bb2633abb3192d35f65e50a96f9f7ca878fa2ee7bf5d3fca489c0c60dc79a;` +/// - `transactionIndex = 0x99;` +public struct EventLog: Decodable { + public var address: EthereumAddress + public var blockHash: Data + public var blockNumber: BigUInt + public var data: Data + public var logIndex: BigUInt + public var removed: Bool + public var topics: [Data] + public var transactionHash: Data + public var transactionIndex: BigUInt + + enum CodingKeys: String, CodingKey { + case address + case blockHash + case blockNumber + case data + case logIndex + case removed + case topics + case transactionHash + case transactionIndex + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let address = try container.decode(EthereumAddress.self, forKey: .address) + self.address = address + + self.blockNumber = try container.decodeHex(BigUInt.self, forKey: .blockNumber) + + self.blockHash = try container.decodeHex(Data.self, forKey: .blockHash) + + self.transactionIndex = try container.decodeHex(BigUInt.self, forKey: .transactionIndex) + + self.transactionHash = try container.decodeHex(Data.self, forKey: .transactionHash) + + self.data = try container.decodeHex(Data.self, forKey: .data) + + self.logIndex = try container.decodeHex(BigUInt.self, forKey: .logIndex) + + let removed = try? container.decodeHex(BigUInt.self, forKey: .removed) + self.removed = removed == 1 ? true : false + + let topicsStrings = try container.decode([String].self, forKey: .topics) + + self.topics = try topicsStrings.map { + guard let topic = Data.fromHex($0) else { throw Web3Error.dataError } + return topic + } + } +} + +extension EventLog: APIResultType { } diff --git a/Sources/web3swift/Convenience/SECP256k1.swift b/Sources/Core/Structure/SECP256k1.swift similarity index 100% rename from Sources/web3swift/Convenience/SECP256k1.swift rename to Sources/Core/Structure/SECP256k1.swift diff --git a/Sources/Core/Structure/Transaction/TransactionDetails.swift b/Sources/Core/Structure/Transaction/TransactionDetails.swift new file mode 100644 index 000000000..65ebb792d --- /dev/null +++ b/Sources/Core/Structure/Transaction/TransactionDetails.swift @@ -0,0 +1,30 @@ +// +// TransactionDetails.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +public struct TransactionDetails: Decodable { + public var blockHash: Data? + public var blockNumber: BigUInt? + public var transactionIndex: BigUInt? + public var transaction: EthereumTransaction + + enum CodingKeys: String, CodingKey { + case blockHash + case blockNumber + case transactionIndex + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.blockNumber = try? container.decodeHex(BigUInt.self, forKey: .blockNumber) + self.blockHash = try? container.decodeHex(Data.self, forKey: .blockHash) + self.transactionIndex = try? container.decodeHex(BigUInt.self, forKey: .transactionIndex) + self.transaction = try EthereumTransaction(from: decoder) + } +} \ No newline at end of file diff --git a/Sources/Core/Structure/Transaction/TransactionInBlock.swift b/Sources/Core/Structure/Transaction/TransactionInBlock.swift new file mode 100644 index 000000000..b2a2e7f0b --- /dev/null +++ b/Sources/Core/Structure/Transaction/TransactionInBlock.swift @@ -0,0 +1,26 @@ +// +// TransactionInBlock.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation + +public enum TransactionInBlock: Decodable { + case hash(Data) + case transaction(EthereumTransaction) + case null + + public init(from decoder: Decoder) throws { + let value = try decoder.singleValueContainer() + if let string = try? value.decode(String.self) { + guard let d = Data.fromHex(string) else {throw Web3Error.dataError} + self = .hash(d) + } else if let transaction = try? value.decode(EthereumTransaction.self) { + self = .transaction(transaction) + } else { + self = .null + } + } +} diff --git a/Sources/Core/Structure/Transaction/TransactionReceipt.swift b/Sources/Core/Structure/Transaction/TransactionReceipt.swift new file mode 100644 index 000000000..6ff2787b4 --- /dev/null +++ b/Sources/Core/Structure/Transaction/TransactionReceipt.swift @@ -0,0 +1,74 @@ +// +// TransactionReceipt.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +public struct TransactionReceipt: Decodable { + public var transactionHash: Data + public var blockHash: Data + public var blockNumber: BigUInt + public var transactionIndex: BigUInt + public var contractAddress: EthereumAddress? + public var cumulativeGasUsed: BigUInt + public var gasUsed: BigUInt + public var logs: [EventLog] + public var status: TXStatus + public var logsBloom: EthereumBloomFilter? + + public enum TXStatus { + case ok + case failed + case notYetProcessed + } + + enum CodingKeys: String, CodingKey { + case blockHash + case blockNumber + case transactionHash + case transactionIndex + case contractAddress + case cumulativeGasUsed + case gasUsed + case logs + case logsBloom + case status + } + + static func notProcessed(transactionHash: Data) -> TransactionReceipt { + TransactionReceipt(transactionHash: transactionHash, blockHash: Data(), blockNumber: BigUInt(0), transactionIndex: BigUInt(0), contractAddress: nil, cumulativeGasUsed: BigUInt(0), gasUsed: BigUInt(0), logs: [EventLog](), status: .notYetProcessed, logsBloom: nil) + } +} + +extension TransactionReceipt { + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.blockNumber = try container.decodeHex(BigUInt.self, forKey: .blockNumber) + + self.blockHash = try container.decodeHex(Data.self, forKey: .blockHash) + + self.transactionIndex = try container.decodeHex(BigUInt.self, forKey: .transactionIndex) + + self.transactionHash = try container.decodeHex(Data.self, forKey: .transactionHash) + + self.contractAddress = try? container.decodeIfPresent(EthereumAddress.self, forKey: .contractAddress) + + self.cumulativeGasUsed = try container.decodeHex(BigUInt.self, forKey: .cumulativeGasUsed) + + self.gasUsed = try container.decodeHex(BigUInt.self, forKey: .gasUsed) + + let status = try? container.decodeHex(BigUInt.self, forKey: .status) + switch status { + case nil: self.status = .notYetProcessed + case 1: self.status = .ok + default: self.status = .failed + } + + self.logs = try container.decode([EventLog].self, forKey: .logs) + } +} diff --git a/Sources/Core/Structure/TxPool/TxPoolContent.swift b/Sources/Core/Structure/TxPool/TxPoolContent.swift new file mode 100644 index 000000000..6e4e57734 --- /dev/null +++ b/Sources/Core/Structure/TxPool/TxPoolContent.swift @@ -0,0 +1,77 @@ +// +// TxPoolContent.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +public struct TxPoolContent: Decodable { + public var pending: [EthereumAddress: [TxPoolContentForNonce]] + public var queued: [EthereumAddress: [TxPoolContentForNonce]] + + enum CodingKeys: String, CodingKey { + case pending + case queued + } + + fileprivate static func decodePoolContentForKey(container: KeyedDecodingContainer, key: KeyedDecodingContainer.Key) throws -> [EthereumAddress: [TxPoolContentForNonce]] { + let raw = try container.nestedContainer(keyedBy: AdditionalDataCodingKeys.self, forKey: key) + var result = [EthereumAddress: [TxPoolContentForNonce]]() + for addressKey in raw.allKeys { + let addressString = addressKey.stringValue + guard let address = EthereumAddress(addressString, type: .normal, ignoreChecksum: true) else { + throw Web3Error.dataError + } + let nestedContainer = try raw.nestedContainer(keyedBy: AdditionalDataCodingKeys.self, forKey: addressKey) + var perNonceInformation = [TxPoolContentForNonce]() + perNonceInformation.reserveCapacity(nestedContainer.allKeys.count) + for nonceKey in nestedContainer.allKeys { + guard let nonce = BigUInt(nonceKey.stringValue) else { + throw Web3Error.dataError + } + let n = try? nestedContainer.nestedUnkeyedContainer(forKey: nonceKey) + if n != nil { + let details = try nestedContainer.decode([TransactionDetails].self, forKey: nonceKey) + let content = TxPoolContentForNonce(nonce: nonce, details: details) + perNonceInformation.append(content) + } else { + let detail = try nestedContainer.decode(TransactionDetails.self, forKey: nonceKey) + let content = TxPoolContentForNonce(nonce: nonce, details: [detail]) + perNonceInformation.append(content) + } + } + result[address] = perNonceInformation + } + return result + } + + fileprivate struct AdditionalDataCodingKeys: CodingKey { + var stringValue: String + init?(stringValue: String) { + self.stringValue = stringValue + } + + var intValue: Int? + init?(intValue: Int) { + return nil + } + } +} + +extension TxPoolContent: APIResultType { } + +extension TxPoolContent { + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.pending = try TxPoolContent.decodePoolContentForKey(container: container, key: .pending) + self.queued = try TxPoolContent.decodePoolContentForKey(container: container, key: .queued) + } +} + +public struct TxPoolContentForNonce { + public var nonce: BigUInt + public var details: [TransactionDetails] +} diff --git a/Sources/Core/Structure/TxPool/TxPoolStatus.swift b/Sources/Core/Structure/TxPool/TxPoolStatus.swift new file mode 100644 index 000000000..d2d159a21 --- /dev/null +++ b/Sources/Core/Structure/TxPool/TxPoolStatus.swift @@ -0,0 +1,29 @@ +// +// TxPoolStatus.swift +// +// +// Created by Yaroslav Yashin on 12.07.2022. +// + +import Foundation +import BigInt + +public struct TxPoolStatus: Decodable { + public var pending: BigUInt + public var queued: BigUInt + + enum CodingKeys: String, CodingKey { + case pending + case queued + } +} + +extension TxPoolStatus: APIResultType { } + +public extension TxPoolStatus { + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.pending = try container.decodeHex(BigUInt.self, forKey: .pending) + self.queued = try container.decodeHex(BigUInt.self, forKey: .queued) + } +} diff --git a/Sources/Core/Structure/Web3Provider.swift b/Sources/Core/Structure/Web3Provider.swift new file mode 100644 index 000000000..6bd612797 --- /dev/null +++ b/Sources/Core/Structure/Web3Provider.swift @@ -0,0 +1,15 @@ +// +// Web3Provider.swift +// +// +// Created by Yaroslav Yashin on 11.07.2022. +// + +import Foundation + +public protocol Web3Provider { + var network: Networks? {get set} + var attachedKeystoreManager: KeystoreManager? {get set} + var url: URL {get} + var session: URLSession {get} +} diff --git a/Sources/web3swift/Transaction/AbstractEnvelope.swift b/Sources/Core/Transaction/AbstractEnvelope.swift similarity index 99% rename from Sources/web3swift/Transaction/AbstractEnvelope.swift rename to Sources/Core/Transaction/AbstractEnvelope.swift index c605b7470..2912cb56d 100644 --- a/Sources/web3swift/Transaction/AbstractEnvelope.swift +++ b/Sources/Core/Transaction/AbstractEnvelope.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -7,6 +7,7 @@ import Foundation import BigInt + /* AbstractEnvelope is the main protocol definition to enable support for different transaction types. it defines the basic parameters and methods required by all transaction types. diff --git a/Sources/web3swift/Transaction/BloomFilter.swift b/Sources/Core/Transaction/BloomFilter.swift similarity index 100% rename from Sources/web3swift/Transaction/BloomFilter.swift rename to Sources/Core/Transaction/BloomFilter.swift diff --git a/Sources/web3swift/Transaction/EIP1559Envelope.swift b/Sources/Core/Transaction/EIP1559Envelope.swift similarity index 99% rename from Sources/web3swift/Transaction/EIP1559Envelope.swift rename to Sources/Core/Transaction/EIP1559Envelope.swift index 0a2fc7c24..21e331645 100644 --- a/Sources/web3swift/Transaction/EIP1559Envelope.swift +++ b/Sources/Core/Transaction/EIP1559Envelope.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // diff --git a/Sources/web3swift/Transaction/EIP2718Envelope.swift b/Sources/Core/Transaction/EIP2718Envelope.swift similarity index 98% rename from Sources/web3swift/Transaction/EIP2718Envelope.swift rename to Sources/Core/Transaction/EIP2718Envelope.swift index 8089d785b..e44307112 100644 --- a/Sources/web3swift/Transaction/EIP2718Envelope.swift +++ b/Sources/Core/Transaction/EIP2718Envelope.swift @@ -1,4 +1,3 @@ -// Package: web3swift // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // diff --git a/Sources/web3swift/Transaction/EIP2930Envelope.swift b/Sources/Core/Transaction/EIP2930Envelope.swift similarity index 99% rename from Sources/web3swift/Transaction/EIP2930Envelope.swift rename to Sources/Core/Transaction/EIP2930Envelope.swift index 7d9eaa5df..64ddddd50 100644 --- a/Sources/web3swift/Transaction/EIP2930Envelope.swift +++ b/Sources/Core/Transaction/EIP2930Envelope.swift @@ -1,4 +1,3 @@ -// Package: web3swift // // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. diff --git a/Sources/web3swift/Transaction/EnvelopeFactory.swift b/Sources/Core/Transaction/EnvelopeFactory.swift similarity index 99% rename from Sources/web3swift/Transaction/EnvelopeFactory.swift rename to Sources/Core/Transaction/EnvelopeFactory.swift index 131a4f3e7..e172d1dd6 100644 --- a/Sources/web3swift/Transaction/EnvelopeFactory.swift +++ b/Sources/Core/Transaction/EnvelopeFactory.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // diff --git a/Sources/web3swift/Transaction/EthereumMetadata.swift b/Sources/Core/Transaction/EthereumMetadata.swift similarity index 91% rename from Sources/web3swift/Transaction/EthereumMetadata.swift rename to Sources/Core/Transaction/EthereumMetadata.swift index 4aec23e0d..c669587f6 100644 --- a/Sources/web3swift/Transaction/EthereumMetadata.swift +++ b/Sources/Core/Transaction/EthereumMetadata.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -14,24 +14,24 @@ import BigInt public struct EthereumMetadata { /// hash for the block that contains this transaction on chain - var blockHash: Data? + public var blockHash: Data? /// block number for the block containing this transaction on chain - var blockNumber: BigUInt? + public var blockNumber: BigUInt? /// index for this transaction within the containing block - var transactionIndex: UInt? + public var transactionIndex: UInt? /// hash for this transaction as returned by the node [not computed] /// this can be used for validation against the computed hash returned /// by the transaction envelope. - var transactionHash: Data? + public var transactionHash: Data? /// gasPrice value returned by the node /// note this is a duplicate value for legacy and EIP-2930 transaction types /// but is included here since EIP-1559 does not contain a `gasPrice`, but /// nodes still report the value. - var gasPrice: BigUInt? + public var gasPrice: BigUInt? } public extension EthereumMetadata { diff --git a/Sources/web3swift/Transaction/EthereumParameters.swift b/Sources/Core/Transaction/EthereumParameters.swift similarity index 77% rename from Sources/web3swift/Transaction/EthereumParameters.swift rename to Sources/Core/Transaction/EthereumParameters.swift index 68a627af8..0239c6e22 100644 --- a/Sources/web3swift/Transaction/EthereumParameters.swift +++ b/Sources/Core/Transaction/EthereumParameters.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -49,6 +49,20 @@ public struct EthereumParameters { /// access list for contract execution (EIP-2930 and EIP-1559 only) public var accessList: [AccessListEntry]? + + public init(type: TransactionType? = nil, to: EthereumAddress? = nil, nonce: BigUInt? = nil, chainID: BigUInt? = nil, value: BigUInt? = nil, data: Data? = nil, gasLimit: BigUInt? = nil, gasPrice: BigUInt? = nil, maxFeePerGas: BigUInt? = nil, maxPriorityFeePerGas: BigUInt? = nil, accessList: [AccessListEntry]? = nil) { + self.type = type + self.to = to + self.nonce = nonce + self.chainID = chainID + self.value = value + self.data = data + self.gasLimit = gasLimit + self.gasPrice = gasPrice + self.maxFeePerGas = maxFeePerGas + self.maxPriorityFeePerGas = maxPriorityFeePerGas + self.accessList = accessList + } } public extension EthereumParameters { diff --git a/Sources/web3swift/Transaction/EthereumTransaction.swift b/Sources/Core/Transaction/EthereumTransaction.swift similarity index 99% rename from Sources/web3swift/Transaction/EthereumTransaction.swift rename to Sources/Core/Transaction/EthereumTransaction.swift index 534726015..c2e53123d 100755 --- a/Sources/web3swift/Transaction/EthereumTransaction.swift +++ b/Sources/Core/Transaction/EthereumTransaction.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -82,7 +82,7 @@ public struct EthereumTransaction: CustomStringConvertible { /// the address of the sender of the transaction recovered from the signature public var sender: EthereumAddress? { guard let publicKey = self.recoverPublicKey() else { return nil } - return Web3.Utils.publicToAddress(publicKey) + return Utilities.publicToAddress(publicKey) } /// the transaction hash diff --git a/Sources/web3swift/Transaction/LegacyEnvelope.swift b/Sources/Core/Transaction/LegacyEnvelope.swift similarity index 99% rename from Sources/web3swift/Transaction/LegacyEnvelope.swift rename to Sources/Core/Transaction/LegacyEnvelope.swift index 6628b9f3f..ea6b4d7cf 100644 --- a/Sources/web3swift/Transaction/LegacyEnvelope.swift +++ b/Sources/Core/Transaction/LegacyEnvelope.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // diff --git a/Sources/web3swift/Web3/Web3+Options.swift b/Sources/Core/Transaction/TransactionOptions.swift similarity index 92% rename from Sources/web3swift/Web3/Web3+Options.swift rename to Sources/Core/Transaction/TransactionOptions.swift index bba7fa3ea..190934573 100755 --- a/Sources/web3swift/Web3/Web3+Options.swift +++ b/Sources/Core/Transaction/TransactionOptions.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -82,6 +82,21 @@ public struct TransactionOptions { opts.callOnBlock = .pending return opts } + + public init(type: TransactionType? = nil, to: EthereumAddress? = nil, from: EthereumAddress? = nil, chainID: BigUInt? = nil, gasLimit: GasLimitPolicy? = nil, gasPrice: GasPricePolicy? = nil, maxFeePerGas: FeePerGasPolicy? = nil, maxPriorityFeePerGas: FeePerGasPolicy? = nil, value: BigUInt? = nil, nonce: NoncePolicy? = nil, callOnBlock: BlockNumber? = nil, accessList: [AccessListEntry]? = nil) { + self.type = type + self.to = to + self.from = from + self.chainID = chainID + self.gasLimit = gasLimit + self.gasPrice = gasPrice + self.maxFeePerGas = maxFeePerGas + self.maxPriorityFeePerGas = maxPriorityFeePerGas + self.value = value + self.nonce = nonce + self.callOnBlock = callOnBlock + self.accessList = accessList + } public func resolveNonce(_ suggestedByNode: BigUInt) -> BigUInt { guard let noncePolicy = self.nonce else { return suggestedByNode } diff --git a/Sources/web3swift/Web3/Web3+JSONRPC.swift b/Sources/Core/Transaction/TransactionParameters.swift similarity index 82% rename from Sources/web3swift/Web3/Web3+JSONRPC.swift rename to Sources/Core/Transaction/TransactionParameters.swift index 717b89cc4..03d3128ee 100755 --- a/Sources/web3swift/Web3/Web3+JSONRPC.swift +++ b/Sources/Core/Transaction/TransactionParameters.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -49,10 +49,21 @@ public struct TransactionParameters: Codable { } } +extension TransactionParameters: APIRequestParameterType { } + /// Event filter parameters JSON structure for interaction with Ethereum node. public struct EventFilterParameters: Codable { public var fromBlock: String? public var toBlock: String? public var topics: [[String?]?]? public var address: [String?]? + + public init(fromBlock: String? = nil, toBlock: String? = nil, topics: [[String?]?]? = nil, address: [String?]? = nil) { + self.fromBlock = fromBlock + self.toBlock = toBlock + self.topics = topics + self.address = address + } } + +extension EventFilterParameters: APIRequestParameterType { } diff --git a/Sources/web3swift/EthereumAddress/Extensions.swift b/Sources/Core/Utility/Array+Extension.swift similarity index 64% rename from Sources/web3swift/EthereumAddress/Extensions.swift rename to Sources/Core/Utility/Array+Extension.swift index 0e5ead961..2847d2b2e 100755 --- a/Sources/web3swift/EthereumAddress/Extensions.swift +++ b/Sources/Core/Utility/Array+Extension.swift @@ -58,3 +58,25 @@ extension Array where Element == UInt8 { } } } + +extension Array { + public func split(intoChunksOf chunkSize: Int) -> [[Element]] { + return stride(from: 0, to: self.count, by: chunkSize).map { + let endIndex = ($0.advanced(by: chunkSize) > self.count) ? self.count - $0 : chunkSize + return Array(self[$0..<$0.advanced(by: endIndex)]) + } + } +} + +extension Array where Element: Comparable { + /// Sorts array and drops first and last values. + /// - Returns: Sorted array without first and last values, nil if `array.count` <= 1 + func cropAnomalyValues() -> Self? { + var sortedArray = self.sorted() + // Array should at least have two values to pass that formations. + guard sortedArray.count > 1 else { return nil } + sortedArray.removeLast() + sortedArray.removeFirst() + return sortedArray + } +} diff --git a/Sources/web3swift/Convenience/BigUInt+Extensions.swift b/Sources/Core/Utility/BigUInt+Extension.swift similarity index 52% rename from Sources/web3swift/Convenience/BigUInt+Extensions.swift rename to Sources/Core/Utility/BigUInt+Extension.swift index 786d1f8e4..33b13781c 100755 --- a/Sources/web3swift/Convenience/BigUInt+Extensions.swift +++ b/Sources/Core/Utility/BigUInt+Extension.swift @@ -9,8 +9,8 @@ import Foundation import struct BigInt.BigUInt public extension BigUInt { - init?(_ naturalUnits: String, _ ethereumUnits: Web3.Utils.Units) { - guard let value = Web3.Utils.parseToBigUInt(naturalUnits, units: ethereumUnits) else {return nil} + init?(_ naturalUnits: String, _ ethereumUnits: Utilities.Units) { + guard let value = Utilities.parseToBigUInt(naturalUnits, units: ethereumUnits) else {return nil} self = value } } diff --git a/Sources/web3swift/Convenience/CryptoExtensions.swift b/Sources/Core/Utility/CryptoExtension.swift similarity index 100% rename from Sources/web3swift/Convenience/CryptoExtensions.swift rename to Sources/Core/Utility/CryptoExtension.swift diff --git a/Sources/web3swift/Convenience/Data+Extension.swift b/Sources/Core/Utility/Data+Extension.swift similarity index 89% rename from Sources/web3swift/Convenience/Data+Extension.swift rename to Sources/Core/Utility/Data+Extension.swift index addc10dcf..38ee3b9d2 100755 --- a/Sources/web3swift/Convenience/Data+Extension.swift +++ b/Sources/Core/Utility/Data+Extension.swift @@ -60,19 +60,6 @@ public extension Data { return nil } - static func fromHex(_ hex: String) -> Data? { - let string = hex.lowercased().stripHexPrefix() - let array = Array(hex: string) - if (array.count == 0) { - if (hex == "0x" || hex == "") { - return Data() - } else { - return nil - } - } - return Data(array) - } - func bitsInRange(_ startingBit: Int, _ length: Int) -> UInt64? { // return max of 8 bytes for simplicity, non-public if startingBit + length / 8 > self.count, length > 64, startingBit > 0, length >= 1 {return nil} let bytes = self[(startingBit/8) ..< (startingBit+length+7)/8] diff --git a/Sources/web3swift/Convenience/Decodable+Extensions.swift b/Sources/Core/Utility/Decodable+Extensions.swift similarity index 100% rename from Sources/web3swift/Convenience/Decodable+Extensions.swift rename to Sources/Core/Utility/Decodable+Extensions.swift diff --git a/Sources/web3swift/Convenience/Dictionary+Extension.swift b/Sources/Core/Utility/Dictionary+Extension.swift similarity index 100% rename from Sources/web3swift/Convenience/Dictionary+Extension.swift rename to Sources/Core/Utility/Dictionary+Extension.swift diff --git a/Sources/web3swift/Convenience/Encodable+Extensions.swift b/Sources/Core/Utility/Encodable+Extensions.swift similarity index 100% rename from Sources/web3swift/Convenience/Encodable+Extensions.swift rename to Sources/Core/Utility/Encodable+Extensions.swift diff --git a/Sources/web3swift/Convenience/NSRegularExpressionExtension.swift b/Sources/Core/Utility/NSRegularExpression+Extension.swift similarity index 100% rename from Sources/web3swift/Convenience/NSRegularExpressionExtension.swift rename to Sources/Core/Utility/NSRegularExpression+Extension.swift diff --git a/Sources/web3swift/Convenience/NativeTypesEncoding+Extensions.swift b/Sources/Core/Utility/NativeTypesEncoding+Extension.swift similarity index 95% rename from Sources/web3swift/Convenience/NativeTypesEncoding+Extensions.swift rename to Sources/Core/Utility/NativeTypesEncoding+Extension.swift index b898d6026..7ac3c0647 100755 --- a/Sources/web3swift/Convenience/NativeTypesEncoding+Extensions.swift +++ b/Sources/Core/Utility/NativeTypesEncoding+Extension.swift @@ -7,7 +7,7 @@ import Foundation import BigInt -extension Data { +public extension Data { func setLengthLeft(_ toBytes: UInt64, isNegative: Bool = false) -> Data? { let existingLength = UInt64(self.count) if (existingLength == toBytes) { @@ -43,7 +43,7 @@ extension Data { } } -extension BigInt { +public extension BigInt { func toTwosComplement() -> Data { if (self.sign == BigInt.Sign.plus) { return self.magnitude.serialize() @@ -56,7 +56,7 @@ extension BigInt { } } -extension BigUInt { +public extension BigUInt { func abiEncode(bits: UInt64) -> Data? { let data = self.serialize() let paddedLength = UInt64(ceil((Double(bits)/8.0))) @@ -65,7 +65,7 @@ extension BigUInt { } } -extension BigInt { +public extension BigInt { func abiEncode(bits: UInt64) -> Data? { let isNegative = self < (BigInt(0)) let data = self.toTwosComplement() @@ -75,7 +75,7 @@ extension BigInt { } } -extension BigInt { +public extension BigInt { static func fromTwosComplement(data: Data) -> BigInt { let isPositive = ((data[0] & 128) >> 7) == 0 if (isPositive) { diff --git a/Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift b/Sources/Core/Utility/RIPEMD160+StackOveflow.swift similarity index 100% rename from Sources/web3swift/Convenience/RIPEMD160+StackOveflow.swift rename to Sources/Core/Utility/RIPEMD160+StackOveflow.swift diff --git a/Sources/web3swift/Convenience/String+Extension.swift b/Sources/Core/Utility/String+Extension.swift similarity index 99% rename from Sources/web3swift/Convenience/String+Extension.swift rename to Sources/Core/Utility/String+Extension.swift index 6e3f09fdf..6d8da0c4d 100755 --- a/Sources/web3swift/Convenience/String+Extension.swift +++ b/Sources/Core/Utility/String+Extension.swift @@ -6,7 +6,7 @@ import Foundation -extension String { +public extension String { var fullRange: Range { return startIndex.. Data? { + if publicKey.count == 33 { + guard let decompressedKey = SECP256K1.combineSerializedPublicKeys(keys: [publicKey], outputCompressed: false) else {return nil} + return publicToAddressData(decompressedKey) + } + var stipped = publicKey + if (stipped.count == 65) { + if (stipped[0] != 4) { + return nil + } + stipped = stipped[1...64] + } + if (stipped.count != 64) { + return nil + } + let sha3 = stipped.sha3(.keccak256) + let addressData = sha3[12...31] + return addressData + } + + + /// Convert a public key to the corresponding EthereumAddress. Accepts public keys in compressed (33 bytes), non-compressed (65 bytes) + /// or raw concat(X, Y) (64 bytes) format. + /// + /// Returns the EthereumAddress object. + public static func publicToAddress(_ publicKey: Data) -> EthereumAddress? { + guard let addressData = publicToAddressData(publicKey) else {return nil} + let address = addressData.toHexString().addHexPrefix().lowercased() + return EthereumAddress(address) + } + + + /// Convert the private key (32 bytes of Data) to compressed (33 bytes) or non-compressed (65 bytes) public key. + public static func privateToPublic(_ privateKey: Data, compressed: Bool = false) -> Data? { + guard let publicKey = SECP256K1.privateToPublic(privateKey: privateKey, compressed: compressed) else {return nil} + return publicKey + } + + + /// Convert a public key to the corresponding EthereumAddress. Accepts public keys in compressed (33 bytes), non-compressed (65 bytes) + /// or raw concat(X, Y) (64 bytes) format. + /// + /// Returns a 0x prefixed hex string. + public static func publicToAddressString(_ publicKey: Data) -> String? { + guard let addressData = Utilities.publicToAddressData(publicKey) else {return nil} + let address = addressData.toHexString().addHexPrefix().lowercased() + return address + } + + /// Converts address data (20 bytes) to the 0x prefixed hex string. Does not perform checksumming. + public static func addressDataToString(_ addressData: Data) -> String? { + guard addressData.count == 20 else {return nil} + return addressData.toHexString().addHexPrefix().lowercased() + } + + /// Hashes a personal message by first padding it with the "\u{19}Ethereum Signed Message:\n" string and message length string. + /// Should be used if some arbitrary information should be hashed and signed to prevent signing an Ethereum transaction + /// by accident. + public static func hashPersonalMessage(_ personalMessage: Data) -> Data? { + var prefix = "\u{19}Ethereum Signed Message:\n" + prefix += String(personalMessage.count) + guard let prefixData = prefix.data(using: .ascii) else {return nil} + var data = Data() + if personalMessage.count >= prefixData.count && prefixData == personalMessage[0 ..< prefixData.count] { + data.append(personalMessage) + } else { + data.append(prefixData) + data.append(personalMessage) + } + let hash = data.sha3(.keccak256) + return hash + } + + /// Parse a user-supplied string using the number of decimals for particular Ethereum unit. + /// If input is non-numeric or precision is not sufficient - returns nil. + /// Allowed decimal separators are ".", ",". + public static func parseToBigUInt(_ amount: String, units: Utilities.Units = .eth) -> BigUInt? { + let unitDecimals = units.decimals + return parseToBigUInt(amount, decimals: unitDecimals) + } + + /// Parse a user-supplied string using the number of decimals. + /// If input is non-numeric or precision is not sufficient - returns nil. + /// Allowed decimal separators are ".", ",". + public static func parseToBigUInt(_ amount: String, decimals: Int = 18) -> BigUInt? { + let separators = CharacterSet(charactersIn: ".,") + let components = amount.trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: separators) + guard components.count == 1 || components.count == 2 else {return nil} + let unitDecimals = decimals + guard let beforeDecPoint = BigUInt(components[0], radix: 10) else {return nil} + var mainPart = beforeDecPoint*BigUInt(10).power(unitDecimals) + if (components.count == 2) { + let numDigits = components[1].count + guard numDigits <= unitDecimals else {return nil} + guard let afterDecPoint = BigUInt(components[1], radix: 10) else {return nil} + let extraPart = afterDecPoint*BigUInt(10).power(unitDecimals-numDigits) + mainPart = mainPart + extraPart + } + return mainPart + } + + /// Formats a BigInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", + /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. + /// + /// Returns nil of formatting is not possible to satisfy. + public static func formatToEthereumUnits(_ bigNumber: BigInt, toUnits: Utilities.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".") -> String? { + let magnitude = bigNumber.magnitude + guard let formatted = formatToEthereumUnits(magnitude, toUnits: toUnits, decimals: decimals, decimalSeparator: decimalSeparator) else {return nil} + switch bigNumber.sign { + case .plus: + return formatted + case .minus: + return "-" + formatted + } + } + + /// Formats a BigInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", + /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. + /// Fallbacks to scientific format if higher precision is required. + /// + /// Returns nil of formatting is not possible to satisfy. + public static func formatToPrecision(_ bigNumber: BigInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { + let magnitude = bigNumber.magnitude + guard let formatted = formatToPrecision(magnitude, numberDecimals: numberDecimals, formattingDecimals: formattingDecimals, decimalSeparator: decimalSeparator, fallbackToScientific: fallbackToScientific) else {return nil} + switch bigNumber.sign { + case .plus: + return formatted + case .minus: + return "-" + formatted + } + } + + /// Formats a BigUInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", + /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. + /// + /// Returns nil of formatting is not possible to satisfy. + public static func formatToEthereumUnits(_ bigNumber: BigUInt, toUnits: Utilities.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { + return formatToPrecision(bigNumber, numberDecimals: toUnits.decimals, formattingDecimals: decimals, decimalSeparator: decimalSeparator, fallbackToScientific: fallbackToScientific) + } + + /// Formats a BigUInt object to String. The supplied number is first divided into integer and decimal part based on "numberDecimals", + /// then limits the decimal part to "formattingDecimals" symbols and uses a "decimalSeparator" as a separator. + /// Fallbacks to scientific format if higher precision is required. + /// + /// Returns nil of formatting is not possible to satisfy. + public static func formatToPrecision(_ bigNumber: BigUInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { + if bigNumber == 0 { + return "0" + } + let unitDecimals = numberDecimals + var toDecimals = formattingDecimals + if unitDecimals < toDecimals { + toDecimals = unitDecimals + } + let divisor = BigUInt(10).power(unitDecimals) + let (quotient, remainder) = bigNumber.quotientAndRemainder(dividingBy: divisor) + var fullRemainder = String(remainder) + let fullPaddedRemainder = fullRemainder.leftPadding(toLength: unitDecimals, withPad: "0") + let remainderPadded = fullPaddedRemainder[0.. formattingDecimals { + let end = firstDigit+1+formattingDecimals > fullPaddedRemainder.count ? fullPaddedRemainder.count: firstDigit+1+formattingDecimals + remainingDigits = String(fullPaddedRemainder[firstDigit+1 ..< end]) + } else { + remainingDigits = String(fullPaddedRemainder[firstDigit+1 ..< fullPaddedRemainder.count]) + } + if remainingDigits != "" { + fullRemainder = firstDecimalUnit + decimalSeparator + remainingDigits + } else { + fullRemainder = firstDecimalUnit + } + firstDigit = firstDigit + 1 + break + } + } + return fullRemainder + "e-" + String(firstDigit) + } + } + if (toDecimals == 0) { + return String(quotient) + } + return String(quotient) + decimalSeparator + remainderPadded + } + + /// Recover the Ethereum address from recoverable secp256k1 signature. Message is first hashed using the "personal hash" protocol. + /// BE WARNED - changing a message will result in different Ethereum address, but not in error. + /// + /// Input parameters should be hex Strings. + static public func personalECRecover(_ personalMessage: String, signature: String) -> EthereumAddress? { + guard let data = Data.fromHex(personalMessage) else {return nil} + guard let sig = Data.fromHex(signature) else {return nil} + return Utilities.personalECRecover(data, signature: sig) + } + + /// Recover the Ethereum address from recoverable secp256k1 signature. Message is first hashed using the "personal hash" protocol. + /// BE WARNED - changing a message will result in different Ethereum address, but not in error. + /// + /// Input parameters should be Data objects. + static public func personalECRecover(_ personalMessage: Data, signature: Data) -> EthereumAddress? { + if signature.count != 65 { return nil} + let rData = signature[0..<32].bytes + let sData = signature[32..<64].bytes + var vData = signature[64] + if vData >= 27 && vData <= 30 { + vData -= 27 + } else if vData >= 31 && vData <= 34 { + vData -= 31 + } else if vData >= 35 && vData <= 38 { + vData -= 35 + } + + guard let signatureData = SECP256K1.marshalSignature(v: vData, r: rData, s: sData) else {return nil} + guard let hash = Utilities.hashPersonalMessage(personalMessage) else {return nil} + guard let publicKey = SECP256K1.recoverPublicKey(hash: hash, signature: signatureData) else {return nil} + return Utilities.publicToAddress(publicKey) + } + + + /// Recover the Ethereum address from recoverable secp256k1 signature. + /// Takes a hash of some message. What message is hashed should be checked by user separately. + /// + /// Input parameters should be Data objects. + static public func hashECRecover(hash: Data, signature: Data) -> EthereumAddress? { + if signature.count != 65 { return nil} + let rData = signature[0..<32].bytes + let sData = signature[32..<64].bytes + var vData = signature[64] + if vData >= 27 && vData <= 30 { + vData -= 27 + } else if vData >= 31 && vData <= 34 { + vData -= 31 + } else if vData >= 35 && vData <= 38 { + vData -= 35 + } + guard let signatureData = SECP256K1.marshalSignature(v: vData, r: rData, s: sData) else {return nil} + guard let publicKey = SECP256K1.recoverPublicKey(hash: hash, signature: signatureData) else {return nil} + return Utilities.publicToAddress(publicKey) + } + + /// returns Ethereum variant of sha3 (keccak256) of data. Returns nil is data is empty + static public func keccak256(_ data: Data) -> Data? { + if data.count == 0 {return nil} + return data.sha3(.keccak256) + } + + /// returns Ethereum variant of sha3 (keccak256) of data. Returns nil is data is empty + static public func sha3(_ data: Data) -> Data? { + if data.count == 0 {return nil} + return data.sha3(.keccak256) + } + + /// returns sha256 of data. Returns nil is data is empty + static public func sha256(_ data: Data) -> Data? { + if data.count == 0 {return nil} + return data.sha256() + } + + /// Unmarshals a 65 byte recoverable EC signature into internal structure. + static func unmarshalSignature(signatureData: Data) -> SECP256K1.UnmarshaledSignature? { + if (signatureData.count != 65) {return nil} + let bytes = signatureData.bytes + let r = Array(bytes[0..<32]) + let s = Array(bytes[32..<64]) + return SECP256K1.UnmarshaledSignature(v: bytes[64], r: Data(r), s: Data(s)) + } + + /// Marshals the V, R and S signature parameters into a 65 byte recoverable EC signature. + static func marshalSignature(v: UInt8, r: [UInt8], s: [UInt8]) -> Data? { + guard r.count == 32, s.count == 32 else {return nil} + var completeSignature = Data(r) + completeSignature.append(Data(s)) + completeSignature.append(Data([v])) + return completeSignature + } + + /// Marshals internal signature structure into a 65 byte recoverable EC signature. + static func marshalSignature(unmarshalledSignature: SECP256K1.UnmarshaledSignature) -> Data { + var completeSignature = Data(unmarshalledSignature.r) + completeSignature.append(Data(unmarshalledSignature.s)) + completeSignature.append(Data([unmarshalledSignature.v])) + return completeSignature + } + + public static func hexToData(_ string: String) -> Data? { + return Data.fromHex(string) + } + + public static func hexToBigUInt(_ string: String) -> BigUInt? { + return BigUInt(string.stripHexPrefix(), radix: 16) + } + + public static func randomBytes(length: Int) -> Data? { + return Data.randomBytes(length: length) + } +} + +extension Utilities { + /// Various units used in Ethereum ecosystem + public enum Units { + case eth + case wei + case Kwei + case Mwei + case Gwei + case Microether + case Finney + + var decimals: Int { + get { + switch self { + case .eth: + return 18 + case .wei: + return 0 + case .Kwei: + return 3 + case .Mwei: + return 6 + case .Gwei: + return 9 + case .Microether: + return 12 + case .Finney: + return 15 + } + } + } + } +} diff --git a/Sources/Core/Web3Error/Web3Error.swift b/Sources/Core/Web3Error/Web3Error.swift new file mode 100644 index 000000000..1c5b5c03f --- /dev/null +++ b/Sources/Core/Web3Error/Web3Error.swift @@ -0,0 +1,62 @@ +// +// Web3Error.swift +// +// +// Created by Yaroslav Yashin on 11.07.2022. +// + +import Foundation + +public enum Web3Error: Error { + case transactionSerializationError + case connectionError + + case dataError + case typeError + case valueError + case serverError(code: Int) + case clientError(code: Int) + + case walletError + case inputError(desc: String) + case nodeError(desc: String) + case processingError(desc: String) + case keystoreError(err: AbstractKeystoreError) + case generalError(err: Error) + case unknownError + + + public var errorDescription: String { + switch self { + + case .transactionSerializationError: + return "Transaction Serialization Error" + case .connectionError: + return "Connection Error" + case .dataError: + return "Data Error" + case .walletError: + return "Wallet Error" + case .inputError(let desc): + return desc + case .nodeError(let desc): + return desc + case .processingError(let desc): + return desc + case .keystoreError(let err): + return err.localizedDescription + case .generalError(let err): + return err.localizedDescription + case .unknownError: + return "Unknown Error" + case .typeError: + return "Unsupported type" + case let .serverError(code: code): + return "Server error: \(code)" + case let .clientError(code: code): + return "Client error: \(code)" + case .valueError: + return "You're passing value that doesn't supported by this method." + } + } +} diff --git a/Sources/Linting.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Sources/Linting.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Sources/Linting.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Sources/web3swift/API/APIRequestParameter.swift b/Sources/web3swift/API/APIRequestParameter.swift deleted file mode 100644 index 9cd57fcf7..000000000 --- a/Sources/web3swift/API/APIRequestParameter.swift +++ /dev/null @@ -1,203 +0,0 @@ -// -// Web3+APIRequestParameter.swift -// Web3swift -// -// Created by Yaroslav on 24.05.2022. -// - -import Foundation - -/// 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 `RequestParameter`s belongs on hardcoded supported types. -/// -/// Please see `RequestParameter` documentation for more details. -protocol APIRequestParameterType: Encodable { } - - -extension Int: APIRequestParameterType { } - -extension UInt: APIRequestParameterType { } - -extension Double: APIRequestParameterType { } - -extension String: APIRequestParameterType { } - -extension Bool: APIRequestParameterType { } - -extension Array: APIRequestParameterType where Element: APIRequestParameterElementType { } - - -protocol APIRequestParameterElementType: Encodable { } - -extension TransactionParameters: APIRequestParameterType { } - -extension EventFilterParameters: APIRequestParameterType { } - -extension Int: APIRequestParameterElementType { } - -extension UInt: APIRequestParameterElementType { } - -extension Double: APIRequestParameterElementType { } - -extension String: APIRequestParameterElementType { } - -extension Bool: APIRequestParameterElementType { } - -/** - 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 `RequestParameter` to not to `[RequestParameter.int(1)]`, but to `[1]`. - - Here's an example of using this enum in field. - ```swift - let jsonRPCParams: [APIRequestParameterType] = [ - .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]]` - ``` - */ -enum RequestParameter { - case int(Int) - case intArray([Int]) - - case uint(UInt) - case uintArray([UInt]) - - case double(Double) - case doubleArray([Double]) - - case string(String) - case stringArray([String]) - - case bool(Bool) - case boolArray([Bool]) - - case transaction(TransactionParameters) - case eventFilter(EventFilterParameters) -} - - -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 `RequestParameter.int(12)` in your code. - */ - 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 - switch type(of: rawValue) { - case is Int.Type: self = .int(rawValue as! Int) - case is [Int].Type: self = .intArray(rawValue as! [Int]) - - 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]) - - 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 [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 - } - // swiftlint:enable force_cast - } - - /// Returning associated value of the enum case. - 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 - 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 .boolArray(value): return value - - case let .transaction(value): return value - case let .eventFilter(value): return value - } - } -} - -extension RequestParameter: Encodable { - /** - This encoder encodes `RequestParameter` assotiated value ignoring self value - - This is required to encode mixed types array, like - - ```swift - let someArray: [RequestParameter] = [ - .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]]` - ``` - */ - 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 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]) - - 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 [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/Contract/ComparisonExtensions.swift b/Sources/web3swift/Contract/ComparisonExtensions.swift index a62fb7efb..86fa86935 100755 --- a/Sources/web3swift/Contract/ComparisonExtensions.swift +++ b/Sources/web3swift/Contract/ComparisonExtensions.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension BigUInt: EventFilterComparable { public func isEqualTo(_ other: AnyObject) -> Bool { diff --git a/Sources/web3swift/Contract/ContractProtocol.swift b/Sources/web3swift/Contract/ContractProtocol.swift index eca4251bf..d821f9c07 100755 --- a/Sources/web3swift/Contract/ContractProtocol.swift +++ b/Sources/web3swift/Contract/ContractProtocol.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core public protocol ContractProtocol { var address: EthereumAddress? {get set} diff --git a/Sources/web3swift/Contract/EthereumContract.swift b/Sources/web3swift/Contract/EthereumContract.swift index ca307a54d..4ce4ab5c9 100755 --- a/Sources/web3swift/Contract/EthereumContract.swift +++ b/Sources/web3swift/Contract/EthereumContract.swift @@ -5,6 +5,7 @@ import Foundation import BigInt +import Core public struct EthereumContract: ContractProtocol { public var transactionOptions: TransactionOptions? = TransactionOptions.defaultOptions diff --git a/Sources/web3swift/Contract/EthereumFilterEncodingExtensions.swift b/Sources/web3swift/Contract/EthereumFilterEncodingExtensions.swift index 49dc9dced..769c70f98 100755 --- a/Sources/web3swift/Contract/EthereumFilterEncodingExtensions.swift +++ b/Sources/web3swift/Contract/EthereumFilterEncodingExtensions.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension BigUInt: EventFilterEncodable { public func eventFilterEncoded() -> String? { diff --git a/Sources/web3swift/Contract/EventFiltering.swift b/Sources/web3swift/Contract/EventFiltering.swift index 9082c796f..bc7ed0079 100755 --- a/Sources/web3swift/Contract/EventFiltering.swift +++ b/Sources/web3swift/Contract/EventFiltering.swift @@ -5,6 +5,7 @@ // import Foundation +import Core internal func filterLogs(decodedLogs: [EventParserResultProtocol], eventFilter: EventFilter) -> [EventParserResultProtocol] { let filteredLogs = decodedLogs.filter { (result) -> Bool in diff --git a/Sources/web3swift/Convenience/Array+Extension.swift b/Sources/web3swift/Convenience/Array+extensions.swift old mode 100755 new mode 100644 similarity index 50% rename from Sources/web3swift/Convenience/Array+Extension.swift rename to Sources/web3swift/Convenience/Array+extensions.swift index d44f96c31..18f3b8aa6 --- a/Sources/web3swift/Convenience/Array+Extension.swift +++ b/Sources/web3swift/Convenience/Array+extensions.swift @@ -1,34 +1,13 @@ -// web3swift // -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. +// Array+extensions.swift +// +// +// Created by Yaroslav Yashin on 11.07.2022. // import Foundation import BigInt -extension Array { - public func split(intoChunksOf chunkSize: Int) -> [[Element]] { - return stride(from: 0, to: self.count, by: chunkSize).map { - let endIndex = ($0.advanced(by: chunkSize) > self.count) ? self.count - $0 : chunkSize - return Array(self[$0..<$0.advanced(by: endIndex)]) - } - } -} - -extension Array where Element: Comparable { - /// Sorts array and drops most and least values. - /// - Returns: Sorted array without most and least values, nil if `array.count` <= 2 - func cropAnomalyValues() -> Self? { - var sortedArray = self.sorted() - // Array should at least counts two to pass that formations. - guard sortedArray.count > 1 else { return nil } - sortedArray.removeLast() - sortedArray.removeFirst() - return sortedArray - } -} - extension Array where Element: BinaryInteger { // TODO: Make me generic /// Calculates mean value of a dataset diff --git a/Sources/web3swift/EthereumABI/ABIDecoding.swift b/Sources/web3swift/EthereumABI/ABIDecoding.swift index f0e92c305..861d99d4c 100755 --- a/Sources/web3swift/EthereumABI/ABIDecoding.swift +++ b/Sources/web3swift/EthereumABI/ABIDecoding.swift @@ -5,6 +5,7 @@ import Foundation import BigInt +import Core public struct ABIDecoder { } diff --git a/Sources/web3swift/EthereumABI/ABIElements.swift b/Sources/web3swift/EthereumABI/ABIElements.swift index 5085dd495..b4ef5830f 100755 --- a/Sources/web3swift/EthereumABI/ABIElements.swift +++ b/Sources/web3swift/EthereumABI/ABIElements.swift @@ -5,6 +5,7 @@ import Foundation import BigInt +import Core public extension ABI { // JSON Decoding diff --git a/Sources/web3swift/EthereumABI/ABIEncoding.swift b/Sources/web3swift/EthereumABI/ABIEncoding.swift index c0b32c2d3..76e368c63 100755 --- a/Sources/web3swift/EthereumABI/ABIEncoding.swift +++ b/Sources/web3swift/EthereumABI/ABIEncoding.swift @@ -5,6 +5,7 @@ import Foundation import BigInt +import Core public struct ABIEncoder { } diff --git a/Sources/web3swift/EthereumABI/ABIParameterTypes.swift b/Sources/web3swift/EthereumABI/ABIParameterTypes.swift index ca43bcbb0..148514775 100755 --- a/Sources/web3swift/EthereumABI/ABIParameterTypes.swift +++ b/Sources/web3swift/EthereumABI/ABIParameterTypes.swift @@ -5,6 +5,7 @@ import Foundation import BigInt +import Core extension ABI.Element { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift index 4486067b8..9b62b2466 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+Call.swift @@ -5,6 +5,7 @@ // import Foundation +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift index 486626b1b..c76b1f87c 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+EstimateGas.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift index a1c8e06b4..87ae1c38b 100644 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+FeeHistory.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core extension Web3.Oracle.FeeHistory: APIResultType { } diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift index 8b8bbd7c0..71189498c 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetAccounts.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { public func ownedAccounts() async throws -> [EthereumAddress] { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift index 05aa2e49e..c964a4c02 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBalance.swift @@ -5,7 +5,7 @@ // import Foundation - +import Core import BigInt extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift index 20f2dd2e6..69af6288a 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByHash.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift index 4d7feb07c..696aaaf4c 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockByNumber.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift index 1ab23a192..7c45a87b4 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetBlockNumber.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift index f90c574ba..c7616fcb2 100644 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetCode.swift @@ -6,7 +6,7 @@ // import Foundation - +import Core import BigInt extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift index afa45f950..5359dd345 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetGasPrice.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift index 072bc0642..f3c82a3aa 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionCount.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift index 9adbd15e8..eda56950d 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionDetails.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension TransactionDetails: APIResultType { } diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift index e15a88649..de1890b10 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+GetTransactionReceipt.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension TransactionReceipt: APIResultType { } diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift index 9d89334cf..e1a9b2aaa 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendRawTransaction.swift @@ -5,6 +5,7 @@ // import Foundation +import Core extension web3.Eth { @@ -27,3 +28,9 @@ extension web3.Eth { return result } } + + +public struct TransactionSendingResult { + public var transaction: EthereumTransaction + public var hash: String +} diff --git a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift index ab6d632ea..3f6f307f7 100755 --- a/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift +++ b/Sources/web3swift/EthereumAPICalls/Ethereum/Eth+SendTransaction.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Eth { diff --git a/Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift index ef89215ad..248c097f4 100755 --- a/Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift +++ b/Sources/web3swift/EthereumAPICalls/Personal/Personal+CreateAccount.swift @@ -6,7 +6,7 @@ import Foundation import BigInt - +import Core extension web3.Personal { public func createAccount(password: String = "web3swift") async throws -> EthereumAddress { diff --git a/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift index fd1d7e023..84cf43c84 100755 --- a/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift +++ b/Sources/web3swift/EthereumAPICalls/Personal/Personal+Sign.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Personal { diff --git a/Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift b/Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift index 58bee98cb..64461be7a 100755 --- a/Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift +++ b/Sources/web3swift/EthereumAPICalls/Personal/Personal+UnlockAccount.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Personal { @@ -23,3 +24,5 @@ extension web3.Personal { return response.result } } + +extension Bool: APIResultType { } diff --git a/Sources/web3swift/EthereumAPICalls/TxPool.swift b/Sources/web3swift/EthereumAPICalls/TxPool.swift index 084375774..535957658 100755 --- a/Sources/web3swift/EthereumAPICalls/TxPool.swift +++ b/Sources/web3swift/EthereumAPICalls/TxPool.swift @@ -6,7 +6,7 @@ import Foundation import BigInt - +import Core extension web3.TxPool { // public func txPoolInspect() async throws -> [String: [String: [String: String]]] { diff --git a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift index f66908191..45f788a57 100755 --- a/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift +++ b/Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.BrowserFunctions { @@ -64,9 +65,9 @@ extension web3.BrowserFunctions { vData -= 35 } guard let signatureData = SECP256K1.marshalSignature(v: vData, r: rData, s: sData) else {return nil} - guard let hash = Web3.Utils.hashPersonalMessage(personalMessage) else {return nil} + guard let hash = Utilities.hashPersonalMessage(personalMessage) else {return nil} guard let publicKey = SECP256K1.recoverPublicKey(hash: hash, signature: signatureData) else {return nil} - return Web3.Utils.publicToAddressString(publicKey) + return Utilities.publicToAddressString(publicKey) } public func sendTransaction(_ transactionJSON: [String: Any], password: String = "web3swift") async -> [String: Any]? { diff --git a/Sources/web3swift/HookedFunctions/Web3+Wallet.swift b/Sources/web3swift/HookedFunctions/Web3+Wallet.swift index 67ba935c9..eb4970110 100755 --- a/Sources/web3swift/HookedFunctions/Web3+Wallet.swift +++ b/Sources/web3swift/HookedFunctions/Web3+Wallet.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Web3Wallet { diff --git a/Sources/web3swift/Tokens/ERC1155/Web3+ERC1155.swift b/Sources/web3swift/Tokens/ERC1155/Web3+ERC1155.swift index 43f1a4a8b..c9eb3b02a 100644 --- a/Sources/web3swift/Tokens/ERC1155/Web3+ERC1155.swift +++ b/Sources/web3swift/Tokens/ERC1155/Web3+ERC1155.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core // Multi Token Standard diff --git a/Sources/web3swift/Tokens/ERC1376/Web3+ERC1376.swift b/Sources/web3swift/Tokens/ERC1376/Web3+ERC1376.swift index 639ee097b..6b2d3bb41 100644 --- a/Sources/web3swift/Tokens/ERC1376/Web3+ERC1376.swift +++ b/Sources/web3swift/Tokens/ERC1376/Web3+ERC1376.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core public enum IERC1376DelegateMode: UInt { case PublicMsgSender = 0 @@ -128,7 +128,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -150,7 +150,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -173,7 +173,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -196,7 +196,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -228,10 +228,10 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let eValue = Web3.Utils.parseToBigUInt(expectedValue, decimals: intDecimals) else { + guard let eValue = Utilities.parseToBigUInt(expectedValue, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } - guard let nValue = Web3.Utils.parseToBigUInt(newValue, decimals: intDecimals) else { + guard let nValue = Utilities.parseToBigUInt(newValue, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -254,7 +254,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + guard let amount = Utilities.parseToBigUInt(value, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -277,7 +277,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + guard let amount = Utilities.parseToBigUInt(value, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -319,7 +319,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(data, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(data, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [value] as [AnyObject], transactionOptions: basicOptions)! @@ -341,7 +341,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + guard let amount = Utilities.parseToBigUInt(value, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transferAndCall", parameters: [to, amount, data] as [AnyObject], transactionOptions: basicOptions)! @@ -383,7 +383,7 @@ public class ERC1376: IERC1376, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + guard let amount = Utilities.parseToBigUInt(value, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC1400/Web3+ERC1400.swift b/Sources/web3swift/Tokens/ERC1400/Web3+ERC1400.swift index 105fc912e..0f4ecfe3d 100644 --- a/Sources/web3swift/Tokens/ERC1400/Web3+ERC1400.swift +++ b/Sources/web3swift/Tokens/ERC1400/Web3+ERC1400.swift @@ -7,6 +7,7 @@ // import Foundation import BigInt +import Core // Security Token Standard @@ -125,7 +126,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -147,7 +148,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -170,7 +171,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -201,7 +202,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -262,7 +263,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -285,7 +286,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -308,7 +309,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -331,7 +332,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -363,7 +364,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -386,7 +387,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -476,7 +477,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -499,7 +500,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -522,7 +523,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -545,7 +546,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -568,7 +569,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -591,7 +592,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -612,7 +613,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -634,7 +635,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -656,7 +657,7 @@ public class ERC1400: IERC1400, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -798,7 +799,7 @@ extension ERC1400: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("send", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -820,7 +821,7 @@ extension ERC1400: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("operatorSend", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! @@ -842,7 +843,7 @@ extension ERC1400: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -864,7 +865,7 @@ extension ERC1400: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! diff --git a/Sources/web3swift/Tokens/ERC1410/Web3+ERC1410.swift b/Sources/web3swift/Tokens/ERC1410/Web3+ERC1410.swift index 8d495695c..a43c5efb7 100644 --- a/Sources/web3swift/Tokens/ERC1410/Web3+ERC1410.swift +++ b/Sources/web3swift/Tokens/ERC1410/Web3+ERC1410.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // Partially Fungible Token Standard protocol IERC1410: IERC20 { @@ -104,7 +104,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -126,7 +126,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -149,7 +149,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -181,7 +181,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -223,7 +223,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -246,7 +246,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -267,7 +267,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -349,7 +349,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -372,7 +372,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -395,7 +395,7 @@ public class ERC1410: IERC1410, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -513,7 +513,7 @@ extension ERC1410: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("send", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -535,7 +535,7 @@ extension ERC1410: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("operatorSend", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! @@ -557,7 +557,7 @@ extension ERC1410: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -579,7 +579,7 @@ extension ERC1410: IERC777 { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! diff --git a/Sources/web3swift/Tokens/ERC1594/Web3+ERC1594.swift b/Sources/web3swift/Tokens/ERC1594/Web3+ERC1594.swift index ab4b7b3e2..f93582632 100644 --- a/Sources/web3swift/Tokens/ERC1594/Web3+ERC1594.swift +++ b/Sources/web3swift/Tokens/ERC1594/Web3+ERC1594.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // Core Security Token Standard protocol IERC1594: IERC20 { @@ -93,7 +93,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -115,7 +115,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -138,7 +138,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -170,7 +170,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -194,7 +194,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -217,7 +217,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -249,7 +249,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -272,7 +272,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -295,7 +295,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -316,7 +316,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -338,7 +338,7 @@ public class ERC1594: IERC1594, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC1633/Web3+ERC1633.swift b/Sources/web3swift/Tokens/ERC1633/Web3+ERC1633.swift index 06662924a..07fdd9a11 100644 --- a/Sources/web3swift/Tokens/ERC1633/Web3+ERC1633.swift +++ b/Sources/web3swift/Tokens/ERC1633/Web3+ERC1633.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // Re-Fungible Token Standard (RFT) protocol IERC1633: IERC20, IERC165 { @@ -80,7 +80,7 @@ public class ERC1633: IERC1633, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -102,7 +102,7 @@ public class ERC1633: IERC1633, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -125,7 +125,7 @@ public class ERC1633: IERC1633, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -157,7 +157,7 @@ public class ERC1633: IERC1633, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC1643/Web3+ERC1643.swift b/Sources/web3swift/Tokens/ERC1643/Web3+ERC1643.swift index 63e0b95a9..ae980b6fa 100644 --- a/Sources/web3swift/Tokens/ERC1643/Web3+ERC1643.swift +++ b/Sources/web3swift/Tokens/ERC1643/Web3+ERC1643.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // Document Management Standard protocol IERC1643: IERC20 { @@ -83,7 +83,7 @@ public class ERC1643: IERC1643, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -105,7 +105,7 @@ public class ERC1643: IERC1643, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -128,7 +128,7 @@ public class ERC1643: IERC1643, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -160,7 +160,7 @@ public class ERC1643: IERC1643, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC1644/Web3+ERC1644.swift b/Sources/web3swift/Tokens/ERC1644/Web3+ERC1644.swift index 31d0179f8..f518661f1 100644 --- a/Sources/web3swift/Tokens/ERC1644/Web3+ERC1644.swift +++ b/Sources/web3swift/Tokens/ERC1644/Web3+ERC1644.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core // Controller Token Operation Standard @@ -82,7 +83,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -104,7 +105,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -127,7 +128,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -159,7 +160,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -192,7 +193,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -215,7 +216,7 @@ public class ERC1644: IERC1644, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC20/Web3+ERC20.swift b/Sources/web3swift/Tokens/ERC20/Web3+ERC20.swift index 8cfd6a0c8..383565e61 100644 --- a/Sources/web3swift/Tokens/ERC20/Web3+ERC20.swift +++ b/Sources/web3swift/Tokens/ERC20/Web3+ERC20.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core // Token Standard @@ -81,7 +82,7 @@ public class ERC20: IERC20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -103,7 +104,7 @@ public class ERC20: IERC20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -126,7 +127,7 @@ public class ERC20: IERC20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -149,7 +150,7 @@ public class ERC20: IERC20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC721/Web3+ERC721.swift b/Sources/web3swift/Tokens/ERC721/Web3+ERC721.swift index 29eb78916..e1249b8ea 100644 --- a/Sources/web3swift/Tokens/ERC721/Web3+ERC721.swift +++ b/Sources/web3swift/Tokens/ERC721/Web3+ERC721.swift @@ -6,7 +6,7 @@ import Foundation import BigInt - +import Core // Non-Fungible Token Standard protocol IERC721: IERC165 { diff --git a/Sources/web3swift/Tokens/ERC721x/Web3+ERC721x.swift b/Sources/web3swift/Tokens/ERC721x/Web3+ERC721x.swift index dec94aab3..82f670890 100644 --- a/Sources/web3swift/Tokens/ERC721x/Web3+ERC721x.swift +++ b/Sources/web3swift/Tokens/ERC721x/Web3+ERC721x.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // A Smarter Token for the Future of Crypto Collectibles // ERC721x is an extension of ERC721 that adds support for multi-fungible tokens and batch transfers, while being fully backward-compatible. diff --git a/Sources/web3swift/Tokens/ERC777/Web3+ERC777.swift b/Sources/web3swift/Tokens/ERC777/Web3+ERC777.swift index f5294f426..75329a120 100644 --- a/Sources/web3swift/Tokens/ERC777/Web3+ERC777.swift +++ b/Sources/web3swift/Tokens/ERC777/Web3+ERC777.swift @@ -7,6 +7,7 @@ // import Foundation import BigInt +import Core // A New Advanced Token Standard @@ -120,7 +121,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -142,7 +143,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -165,7 +166,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -229,7 +230,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("send", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -251,7 +252,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("operatorSend", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! @@ -273,7 +274,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! @@ -295,7 +296,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! @@ -374,7 +375,7 @@ public class ERC777: IERC777, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ERC820/Web3+ERC820.swift b/Sources/web3swift/Tokens/ERC820/Web3+ERC820.swift index 85e697c89..ab0158413 100644 --- a/Sources/web3swift/Tokens/ERC820/Web3+ERC820.swift +++ b/Sources/web3swift/Tokens/ERC820/Web3+ERC820.swift @@ -7,6 +7,7 @@ // import Foundation +import Core // Pseudo-introspection using a registry contract protocol IERC820: IERC165 { diff --git a/Sources/web3swift/Tokens/ERC888/Web3+ERC888.swift b/Sources/web3swift/Tokens/ERC888/Web3+ERC888.swift index 8767bd757..0f7c35979 100644 --- a/Sources/web3swift/Tokens/ERC888/Web3+ERC888.swift +++ b/Sources/web3swift/Tokens/ERC888/Web3+ERC888.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // MultiDimensional Token Standard protocol IERC888 { @@ -69,7 +69,7 @@ public class ERC888: IERC888, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! diff --git a/Sources/web3swift/Tokens/ST20/Web3+ST20.swift b/Sources/web3swift/Tokens/ST20/Web3+ST20.swift index 3f0c5a27b..673ee9ecf 100644 --- a/Sources/web3swift/Tokens/ST20/Web3+ST20.swift +++ b/Sources/web3swift/Tokens/ST20/Web3+ST20.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core // NPolymath Token Standard protocol IST20: IERC20 { @@ -90,7 +90,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -113,7 +113,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -136,7 +136,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [value] as [AnyObject], transactionOptions: basicOptions)! @@ -176,7 +176,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -198,7 +198,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -221,7 +221,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -244,7 +244,7 @@ public class ST20: IST20, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Tokens/ST20/Web3+SecurityToken.swift b/Sources/web3swift/Tokens/ST20/Web3+SecurityToken.swift index 2b41928fb..c280e5c38 100644 --- a/Sources/web3swift/Tokens/ST20/Web3+SecurityToken.swift +++ b/Sources/web3swift/Tokens/ST20/Web3+SecurityToken.swift @@ -8,7 +8,7 @@ import Foundation import BigInt - +import Core /// The Ownable contract has an owner address, and provides basic authorization control functions, this simplifies the implementation of "user permissions". protocol IOwnable { @@ -125,7 +125,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -148,7 +148,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -171,7 +171,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("burn", parameters: [value] as [AnyObject], transactionOptions: basicOptions)! @@ -211,7 +211,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! @@ -233,7 +233,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -256,7 +256,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(newAmount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } @@ -279,7 +279,7 @@ public class SecurityToken: ISecurityToken, ERC20BaseProperties { decimals = decTyped let intDecimals = Int(decimals) - guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + guard let value = Utilities.parseToBigUInt(amount, decimals: intDecimals) else { throw Web3Error.inputError(desc: "Can not parse inputted amount") } diff --git a/Sources/web3swift/Utils/EIP/EIP67Code.swift b/Sources/web3swift/Utils/EIP/EIP67Code.swift index ac46feb5c..f40eb4238 100755 --- a/Sources/web3swift/Utils/EIP/EIP67Code.swift +++ b/Sources/web3swift/Utils/EIP/EIP67Code.swift @@ -7,6 +7,7 @@ import Foundation import CoreImage import BigInt +import Core extension Web3 { diff --git a/Sources/web3swift/Utils/EIP/EIP681.swift b/Sources/web3swift/Utils/EIP/EIP681.swift index 5c8d47264..a5959aa5b 100755 --- a/Sources/web3swift/Utils/EIP/EIP681.swift +++ b/Sources/web3swift/Utils/EIP/EIP681.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension Web3 { diff --git a/Sources/web3swift/Utils/EIP/EIP712.swift b/Sources/web3swift/Utils/EIP/EIP712.swift index ced6d8dcd..10d87d4ff 100644 --- a/Sources/web3swift/Utils/EIP/EIP712.swift +++ b/Sources/web3swift/Utils/EIP/EIP712.swift @@ -1,6 +1,7 @@ import BigInt import CryptoSwift import Foundation +import Core // TODO: Refactor me diff --git a/Sources/web3swift/Utils/ENS/ENS.swift b/Sources/web3swift/Utils/ENS/ENS.swift index 68e7d21b5..28c78fea8 100755 --- a/Sources/web3swift/Utils/ENS/ENS.swift +++ b/Sources/web3swift/Utils/ENS/ENS.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core public class ENS { diff --git a/Sources/web3swift/Utils/ENS/ENSBaseRegistrar.swift b/Sources/web3swift/Utils/ENS/ENSBaseRegistrar.swift index 7929598a4..9dc1c27b3 100644 --- a/Sources/web3swift/Utils/ENS/ENSBaseRegistrar.swift +++ b/Sources/web3swift/Utils/ENS/ENSBaseRegistrar.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core public extension ENS { class BaseRegistrar: ERC721 { diff --git a/Sources/web3swift/Utils/ENS/ENSRegistry.swift b/Sources/web3swift/Utils/ENS/ENSRegistry.swift index 1b385b055..2b9de611f 100644 --- a/Sources/web3swift/Utils/ENS/ENSRegistry.swift +++ b/Sources/web3swift/Utils/ENS/ENSRegistry.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core public extension ENS { class Registry { diff --git a/Sources/web3swift/Utils/ENS/ENSResolver.swift b/Sources/web3swift/Utils/ENS/ENSResolver.swift index 0df80ade7..d6fb0225b 100755 --- a/Sources/web3swift/Utils/ENS/ENSResolver.swift +++ b/Sources/web3swift/Utils/ENS/ENSResolver.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core public extension ENS { class Resolver { diff --git a/Sources/web3swift/Utils/ENS/ENSReverseRegistrar.swift b/Sources/web3swift/Utils/ENS/ENSReverseRegistrar.swift index 503355113..5cb35d4f4 100644 --- a/Sources/web3swift/Utils/ENS/ENSReverseRegistrar.swift +++ b/Sources/web3swift/Utils/ENS/ENSReverseRegistrar.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core public extension ENS { class ReverseRegistrar { diff --git a/Sources/web3swift/Utils/ENS/ETHRegistrarController.swift b/Sources/web3swift/Utils/ENS/ETHRegistrarController.swift index b241fa458..a69982f58 100644 --- a/Sources/web3swift/Utils/ENS/ETHRegistrarController.swift +++ b/Sources/web3swift/Utils/ENS/ETHRegistrarController.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core public extension ENS { class ETHRegistrarController { @@ -65,7 +66,7 @@ public extension ENS { } public func registerName(from: EthereumAddress, name: String, owner: EthereumAddress, duration: UInt, secret: String, price: String) throws -> WriteTransaction { - guard let amount = Web3.Utils.parseToBigUInt(price, units: .eth) else {throw Web3Error.inputError(desc: "Wrong price: no way for parsing to ether units")} + guard let amount = Utilities.parseToBigUInt(price, units: .eth) else {throw Web3Error.inputError(desc: "Wrong price: no way for parsing to ether units")} defaultOptions.value = amount defaultOptions.from = from defaultOptions.to = self.address @@ -74,7 +75,7 @@ public extension ENS { } public func extendNameRegistration(from: EthereumAddress, name: String, duration: UInt32, price: String) throws -> WriteTransaction { - guard let amount = Web3.Utils.parseToBigUInt(price, units: .eth) else {throw Web3Error.inputError(desc: "Wrong price: no way for parsing to ether units")} + guard let amount = Utilities.parseToBigUInt(price, units: .eth) else {throw Web3Error.inputError(desc: "Wrong price: no way for parsing to ether units")} defaultOptions.value = amount defaultOptions.from = from defaultOptions.to = self.address diff --git a/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift b/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift index daf9ed19a..c29c5b6ae 100755 --- a/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift +++ b/Sources/web3swift/Utils/Hooks/NonceMiddleware.swift @@ -6,7 +6,7 @@ import Foundation import BigInt - +import Core extension Web3.Utils { diff --git a/Sources/web3swift/Web3/Web3+Contract.swift b/Sources/web3swift/Web3/Web3+Contract.swift index 25ad1ac83..623eab7ed 100755 --- a/Sources/web3swift/Web3/Web3+Contract.swift +++ b/Sources/web3swift/Web3/Web3+Contract.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3 { diff --git a/Sources/web3swift/Web3/Web3+EIP1559.swift b/Sources/web3swift/Web3/Web3+EIP1559.swift index 1edf13fb4..8689416f7 100644 --- a/Sources/web3swift/Web3/Web3+EIP1559.swift +++ b/Sources/web3swift/Web3/Web3+EIP1559.swift @@ -7,7 +7,7 @@ import Foundation import BigInt - +import Core /// EIP-1559 Base fee extension /// @@ -177,3 +177,8 @@ public extension Web3 { extension Web3.MainChainVersion: Comparable { public static func < (lhs: Web3.MainChainVersion, rhs: Web3.MainChainVersion) -> Bool { return lhs.mainNetFisrtBlockNumber < rhs.mainNetFisrtBlockNumber } } + +extension Block { + /// Returns chain version of mainnet block with such number + var mainChainVersion: Web3.MainChainVersion { Web3.getChainVersion(of: number) } +} diff --git a/Sources/web3swift/Web3/Web3+EventParser.swift b/Sources/web3swift/Web3/Web3+EventParser.swift index c69fec6ba..ff2181c61 100755 --- a/Sources/web3swift/Web3/Web3+EventParser.swift +++ b/Sources/web3swift/Web3/Web3+EventParser.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.web3contract { /// An event parser to fetch events produced by smart-contract related transactions. Should not be constructed manually, but rather by calling the corresponding function on the web3contract object. diff --git a/Sources/web3swift/Web3/Web3+GasOracle.swift b/Sources/web3swift/Web3/Web3+GasOracle.swift index fec0edb5e..7f1e929a0 100644 --- a/Sources/web3swift/Web3/Web3+GasOracle.swift +++ b/Sources/web3swift/Web3/Web3+GasOracle.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core extension Web3 { /// Oracle is the class to do a transaction fee suggestion @@ -90,14 +91,14 @@ extension Web3 { /// It stores about 10 seconds, than it rewrites it with newer data. /// We're explicitly checking that feeHistory is not nil before force unwrapping it. + guard let feeHistory = feeHistory, !forceDropCache, feeHistory.timestamp.distance(to: Date()) < cacheTimeout else { // swiftlint: disable force_unwrapping - guard feeHistory == nil, forceDropCache, feeHistory!.timestamp.distance(to: Date()) > cacheTimeout else { return feeHistory! } - - feeHistory = try await eth.feeHistory(blockCount: blockCount, block: block, percentiles: percentiles) - - /// We're assigning this value the line very above, so it's free to force unwrapping here - return feeHistory! + feeHistory = try await eth.feeHistory(blockCount: blockCount, block: block, percentiles: percentiles) + return feeHistory! // swiftlint: enable force_unwrapping + } + + return feeHistory } /// Suggesting tip values @@ -167,7 +168,7 @@ extension Web3 { return transaction } } - .map { $0.meta?.gasPrice ?? 0 } + .compactMap { $0.meta?.gasPrice ?? 0 } return calculatePercentiles(for: lastNthBlockGasPrice) } diff --git a/Sources/web3swift/Web3/Web3+HttpProvider.swift b/Sources/web3swift/Web3/Web3+HttpProvider.swift index dd662071f..10225986f 100755 --- a/Sources/web3swift/Web3/Web3+HttpProvider.swift +++ b/Sources/web3swift/Web3/Web3+HttpProvider.swift @@ -6,15 +6,7 @@ import Foundation import BigInt - - -/// Providers abstraction for custom providers (websockets, other custom private key managers). At the moment should not be used. -public protocol Web3Provider { - var network: Networks? {get set} - var attachedKeystoreManager: KeystoreManager? {get set} - var url: URL {get} - var session: URLSession {get} -} +import Core /// The default http provider. public class Web3HttpProvider: Web3Provider { diff --git a/Sources/web3swift/Web3/Web3+InfuraProviders.swift b/Sources/web3swift/Web3/Web3+InfuraProviders.swift index 7d2959bf1..123ec2cb5 100755 --- a/Sources/web3swift/Web3/Web3+InfuraProviders.swift +++ b/Sources/web3swift/Web3/Web3+InfuraProviders.swift @@ -6,30 +6,7 @@ import Foundation import BigInt 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: - return "pending" - case .latest: - return "latest" - case .earliest: - return "earliest" - case .exact(let number): - return String(number, radix: 16).addHexPrefix() - } - } -} +import Core /// Custom Web3 HTTP provider of Infura nodes. public final class InfuraProvider: Web3HttpProvider { diff --git a/Sources/web3swift/Web3/Web3+Instance.swift b/Sources/web3swift/Web3/Web3+Instance.swift index 6ae0ca51e..7df21451f 100755 --- a/Sources/web3swift/Web3/Web3+Instance.swift +++ b/Sources/web3swift/Web3/Web3+Instance.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core /// A web3 instance bound to provider. All further functionality is provided under web.*. namespaces. @@ -131,7 +132,7 @@ public class web3 { public class BrowserFunctions: TransactionOptionsInheritable { var provider: Web3Provider // weak var web3: web3? - var web3: web3 + public var web3: web3 public var transactionOptions: TransactionOptions { return self.web3.transactionOptions } diff --git a/Sources/web3swift/Web3/Web3+MutatingTransaction.swift b/Sources/web3swift/Web3/Web3+MutatingTransaction.swift index 54f31189c..acb6fbc26 100755 --- a/Sources/web3swift/Web3/Web3+MutatingTransaction.swift +++ b/Sources/web3swift/Web3/Web3+MutatingTransaction.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core public class WriteTransaction: ReadTransaction { diff --git a/Sources/web3swift/Web3/Web3+Personal.swift b/Sources/web3swift/Web3/Web3+Personal.swift index 2004906d0..d2acaedcc 100755 --- a/Sources/web3swift/Web3/Web3+Personal.swift +++ b/Sources/web3swift/Web3/Web3+Personal.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core extension web3.Personal { @@ -59,7 +60,7 @@ extension web3.Personal { */ public func ecrecover(personalMessage: Data, signature: Data) throws -> EthereumAddress { - guard let recovered = Web3.Utils.personalECRecover(personalMessage, signature: signature) else { + guard let recovered = Utilities.personalECRecover(personalMessage, signature: signature) else { throw Web3Error.dataError } return recovered @@ -77,7 +78,7 @@ extension web3.Personal { */ public func ecrecover(hash: Data, signature: Data) throws -> EthereumAddress { - guard let recovered = Web3.Utils.hashECRecover(hash: hash, signature: signature) else { + guard let recovered = Utilities.hashECRecover(hash: hash, signature: signature) else { throw Web3Error.dataError } return recovered diff --git a/Sources/web3swift/Web3/Web3+ReadingTransaction.swift b/Sources/web3swift/Web3/Web3+ReadingTransaction.swift index ddc52bb52..594fd80e5 100755 --- a/Sources/web3swift/Web3/Web3+ReadingTransaction.swift +++ b/Sources/web3swift/Web3/Web3+ReadingTransaction.swift @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core public class ReadTransaction { public var transaction: EthereumTransaction diff --git a/Sources/web3swift/Web3/Web3+Signing.swift b/Sources/web3swift/Web3/Web3+Signing.swift index 7cc4b3ac1..94fa7d076 100755 --- a/Sources/web3swift/Web3/Web3+Signing.swift +++ b/Sources/web3swift/Web3/Web3+Signing.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -6,6 +6,7 @@ import Foundation import BigInt +import Core public struct Web3Signer { public static func signTX(transaction: inout EthereumTransaction, @@ -25,7 +26,7 @@ public struct Web3Signer { useExtraEntropy: Bool = false) throws -> Data? { var privateKey = try keystore.UNSAFE_getPrivateKeyData(password: password, account: account) defer { Data.zero(&privateKey) } - guard let hash = Web3.Utils.hashPersonalMessage(personalMessage) else { return nil } + guard let hash = Utilities.hashPersonalMessage(personalMessage) else { return nil } let (compressedSignature, _) = SECP256K1.signForRecovery(hash: hash, privateKey: privateKey, useExtraEntropy: useExtraEntropy) return compressedSignature } diff --git a/Sources/web3swift/Web3/Web3+Structures.swift b/Sources/web3swift/Web3/Web3+Structures.swift deleted file mode 100755 index 8971c2c6e..000000000 --- a/Sources/web3swift/Web3/Web3+Structures.swift +++ /dev/null @@ -1,397 +0,0 @@ -// web3swift -// -// Created by Alex Vlasov. -// Copyright © 2018 Alex Vlasov. All rights reserved. -// - -import Foundation -import BigInt - -public struct TransactionDetails: Decodable { - public var blockHash: Data? - public var blockNumber: BigUInt? - public var transactionIndex: BigUInt? - public var transaction: EthereumTransaction - - enum CodingKeys: String, CodingKey { - case blockHash - case blockNumber - case transactionIndex - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.blockNumber = try? container.decodeHex(BigUInt.self, forKey: .blockNumber) - self.blockHash = try? container.decodeHex(Data.self, forKey: .blockHash) - self.transactionIndex = try? container.decodeHex(BigUInt.self, forKey: .transactionIndex) - self.transaction = try EthereumTransaction(from: decoder) - } -} - -public struct TransactionReceipt: Decodable { - public var transactionHash: Data - public var blockHash: Data - public var blockNumber: BigUInt - public var transactionIndex: BigUInt - public var contractAddress: EthereumAddress? - public var cumulativeGasUsed: BigUInt - public var gasUsed: BigUInt - public var logs: [EventLog] - public var status: TXStatus - public var logsBloom: EthereumBloomFilter? - - public enum TXStatus { - case ok - case failed - case notYetProcessed - } - - enum CodingKeys: String, CodingKey { - case blockHash - case blockNumber - case transactionHash - case transactionIndex - case contractAddress - case cumulativeGasUsed - case gasUsed - case logs - case logsBloom - case status - } - - static func notProcessed(transactionHash: Data) -> TransactionReceipt { - TransactionReceipt(transactionHash: transactionHash, blockHash: Data(), blockNumber: BigUInt(0), transactionIndex: BigUInt(0), contractAddress: nil, cumulativeGasUsed: BigUInt(0), gasUsed: BigUInt(0), logs: [EventLog](), status: .notYetProcessed, logsBloom: nil) - } -} - -extension TransactionReceipt { - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - self.blockNumber = try container.decodeHex(BigUInt.self, forKey: .blockNumber) - - self.blockHash = try container.decodeHex(Data.self, forKey: .blockHash) - - self.transactionIndex = try container.decodeHex(BigUInt.self, forKey: .transactionIndex) - - self.transactionHash = try container.decodeHex(Data.self, forKey: .transactionHash) - - self.contractAddress = try? container.decodeIfPresent(EthereumAddress.self, forKey: .contractAddress) - - self.cumulativeGasUsed = try container.decodeHex(BigUInt.self, forKey: .cumulativeGasUsed) - - self.gasUsed = try container.decodeHex(BigUInt.self, forKey: .gasUsed) - - let status = try? container.decodeHex(BigUInt.self, forKey: .status) - switch status { - case nil: self.status = .notYetProcessed - case 1: self.status = .ok - default: self.status = .failed - } - - self.logs = try container.decode([EventLog].self, forKey: .logs) - } -} - -extension EthereumAddress: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let stringValue = try container.decode(String.self) - self.init(stringValue)! - } - - public func encode(to encoder: Encoder) throws { - let value = self.address.lowercased() - var signleValuedCont = encoder.singleValueContainer() - try signleValuedCont.encode(value) - } -} - -public struct EventLog: Decodable { - public var address: EthereumAddress - public var blockHash: Data - public var blockNumber: BigUInt - public var data: Data - public var logIndex: BigUInt - public var removed: Bool - public var topics: [Data] - public var transactionHash: Data - public var transactionIndex: BigUInt - - // address = 0x53066cddbc0099eb6c96785d9b3df2aaeede5da3; - // blockHash = 0x779c1f08f2b5252873f08fd6ec62d75bb54f956633bbb59d33bd7c49f1a3d389; - // blockNumber = 0x4f58f8; - // data = 0x0000000000000000000000000000000000000000000000004563918244f40000; - // logIndex = 0x84; - // removed = 0; - // topics = ( - // 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, - // 0x000000000000000000000000efdcf2c36f3756ce7247628afdb632fa4ee12ec5, - // 0x000000000000000000000000d5395c132c791a7f46fa8fc27f0ab6bacd824484 - // ); - // transactionHash = 0x9f7bb2633abb3192d35f65e50a96f9f7ca878fa2ee7bf5d3fca489c0c60dc79a; - // transactionIndex = 0x99; - - enum CodingKeys: String, CodingKey { - case address - case blockHash - case blockNumber - case data - case logIndex - case removed - case topics - case transactionHash - case transactionIndex - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - let address = try container.decode(EthereumAddress.self, forKey: .address) - self.address = address - - self.blockNumber = try container.decodeHex(BigUInt.self, forKey: .blockNumber) - - self.blockHash = try container.decodeHex(Data.self, forKey: .blockHash) - - self.transactionIndex = try container.decodeHex(BigUInt.self, forKey: .transactionIndex) - - self.transactionHash = try container.decodeHex(Data.self, forKey: .transactionHash) - - self.data = try container.decodeHex(Data.self, forKey: .data) - - self.logIndex = try container.decodeHex(BigUInt.self, forKey: .logIndex) - - let removed = try? container.decodeHex(BigUInt.self, forKey: .removed) - self.removed = removed == 1 ? true : false - - let topicsStrings = try container.decode([String].self, forKey: .topics) - - self.topics = try topicsStrings.map { - guard let topic = Data.fromHex($0) else { throw Web3Error.dataError } - return topic - } - } -} - -extension EventLog: APIResultType { } - -public enum TransactionInBlock: Decodable { - case hash(Data) - case transaction(EthereumTransaction) - case null - - public init(from decoder: Decoder) throws { - let value = try decoder.singleValueContainer() - if let string = try? value.decode(String.self) { - guard let d = Data.fromHex(string) else {throw Web3Error.dataError} - self = .hash(d) - } else if let transaction = try? value.decode(EthereumTransaction.self) { - self = .transaction(transaction) - } else { - self = .null - } - } -} - -/// Ethereum Block -/// -/// Official specification: [](https://github.com/ethereum/execution-apis/blob/main/src/schemas/block.json) -public struct Block: Decodable { - - public var number: BigUInt // MARK: This is optional in web3js, but required in Ethereum JSON-RPC - public var hash: Data // MARK: This is optional in web3js, but required in Ethereum JSON-RPC - public var parentHash: Data - public var nonce: Data? // MARK: This is optional in web3js but required in Ethereum JSON-RPC - public var sha3Uncles: Data - public var logsBloom: EthereumBloomFilter? = nil // MARK: This is optional in web3js but required in Ethereum JSON-RPC - public var transactionsRoot: Data - public var stateRoot: Data - public var receiptsRoot: Data - public var miner: EthereumAddress? = nil // MARK: This is NOT optional in web3js - public var difficulty: BigUInt - public var totalDifficulty: BigUInt - public var extraData: Data - public var size: BigUInt - public var gasLimit: BigUInt - public var gasUsed: BigUInt - public var baseFeePerGas: BigUInt? - public var timestamp: Date - public var transactions: [TransactionInBlock] - public var uncles: [Data] - - enum CodingKeys: String, CodingKey { - case number - case hash - case parentHash - case nonce - case sha3Uncles - case logsBloom - case transactionsRoot - case stateRoot - case receiptsRoot - case miner - case difficulty - case totalDifficulty - case extraData - case size - - case gasLimit - case gasUsed - case baseFeePerGas - - case timestamp - case transactions - case uncles - } - - /// Returns chain version of mainnet block with such number - var mainChainVersion: Web3.MainChainVersion { Web3.getChainVersion(of: number) } -} - -extension Block { - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - self.number = try container.decodeHex(BigUInt.self, forKey: .number) - self.hash = try container.decodeHex(Data.self, forKey: .hash) - self.parentHash = try container.decodeHex(Data.self, forKey: .parentHash) - self.nonce = try? container.decodeHex(Data.self, forKey: .nonce) - self.sha3Uncles = try container.decodeHex(Data.self, forKey: .sha3Uncles) - - if let logsBloomData = try? container.decodeHex(Data.self, forKey: .logsBloom) { - self.logsBloom = EthereumBloomFilter(logsBloomData) - } - - self.transactionsRoot = try container.decodeHex(Data.self, forKey: .transactionsRoot) - self.stateRoot = try container.decodeHex(Data.self, forKey: .stateRoot) - self.receiptsRoot = try container.decodeHex(Data.self, forKey: .receiptsRoot) - - if let minerAddress = try? container.decode(String.self, forKey: .miner) { - self.miner = EthereumAddress(minerAddress) - } - - self.difficulty = try container.decodeHex(BigUInt.self, forKey: .difficulty) - self.totalDifficulty = try container.decodeHex(BigUInt.self, forKey: .totalDifficulty) - self.extraData = try container.decodeHex(Data.self, forKey: .extraData) - self.size = try container.decodeHex(BigUInt.self, forKey: .size) - self.gasLimit = try container.decodeHex(BigUInt.self, forKey: .gasLimit) - self.gasUsed = try container.decodeHex(BigUInt.self, forKey: .gasUsed) - - // optional, since pre EIP-1559 block haven't such property. - self.baseFeePerGas = try? container.decodeHex(BigUInt.self, forKey: .baseFeePerGas) - - self.timestamp = try container.decodeHex(Date.self, forKey: .timestamp) - - self.transactions = try container.decode([TransactionInBlock].self, forKey: .transactions) - - let unclesStrings = try container.decode([String].self, forKey: .uncles) - self.uncles = try unclesStrings.map { - guard let data = Data.fromHex($0) else { throw Web3Error.dataError } - return data - } - } -} - -extension Block: APIResultType { } - -public struct EventParserResult: EventParserResultProtocol { - public var eventName: String - public var transactionReceipt: TransactionReceipt? - public var contractAddress: EthereumAddress - public var decodedResult: [String: Any] - public var eventLog: EventLog? = nil -} - -public struct TransactionSendingResult { - public var transaction: EthereumTransaction - public var hash: String -} - -public struct TxPoolStatus: Decodable { - public var pending: BigUInt - public var queued: BigUInt - - enum CodingKeys: String, CodingKey { - case pending - case queued - } -} - -extension TxPoolStatus: APIResultType { } - -public extension TxPoolStatus { - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.pending = try container.decodeHex(BigUInt.self, forKey: .pending) - self.queued = try container.decodeHex(BigUInt.self, forKey: .queued) - } -} - -public struct TxPoolContent: Decodable { - public var pending: [EthereumAddress: [TxPoolContentForNonce]] - public var queued: [EthereumAddress: [TxPoolContentForNonce]] - - enum CodingKeys: String, CodingKey { - case pending - case queued - } - - fileprivate static func decodePoolContentForKey(container: KeyedDecodingContainer, key: KeyedDecodingContainer.Key) throws -> [EthereumAddress: [TxPoolContentForNonce]] { - let raw = try container.nestedContainer(keyedBy: AdditionalDataCodingKeys.self, forKey: key) - var result = [EthereumAddress: [TxPoolContentForNonce]]() - for addressKey in raw.allKeys { - let addressString = addressKey.stringValue - guard let address = EthereumAddress(addressString, type: .normal, ignoreChecksum: true) else { - throw Web3Error.dataError - } - let nestedContainer = try raw.nestedContainer(keyedBy: AdditionalDataCodingKeys.self, forKey: addressKey) - var perNonceInformation = [TxPoolContentForNonce]() - perNonceInformation.reserveCapacity(nestedContainer.allKeys.count) - for nonceKey in nestedContainer.allKeys { - guard let nonce = BigUInt(nonceKey.stringValue) else { - throw Web3Error.dataError - } - let n = try? nestedContainer.nestedUnkeyedContainer(forKey: nonceKey) - if n != nil { - let details = try nestedContainer.decode([TransactionDetails].self, forKey: nonceKey) - let content = TxPoolContentForNonce(nonce: nonce, details: details) - perNonceInformation.append(content) - } else { - let detail = try nestedContainer.decode(TransactionDetails.self, forKey: nonceKey) - let content = TxPoolContentForNonce(nonce: nonce, details: [detail]) - perNonceInformation.append(content) - } - } - result[address] = perNonceInformation - } - return result - } - - fileprivate struct AdditionalDataCodingKeys: CodingKey { - var stringValue: String - init?(stringValue: String) { - self.stringValue = stringValue - } - - var intValue: Int? - init?(intValue: Int) { - return nil - } - } -} - -extension TxPoolContent: APIResultType { } - -extension TxPoolContent { - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.pending = try TxPoolContent.decodePoolContentForKey(container: container, key: .pending) - self.queued = try TxPoolContent.decodePoolContentForKey(container: container, key: .queued) - } -} - -public struct TxPoolContentForNonce { - public var nonce: BigUInt - public var details: [TransactionDetails] -} diff --git a/Sources/web3swift/Web3/Web3+TxPool.swift b/Sources/web3swift/Web3/Web3+TxPool.swift index b4d598650..c90db2700 100755 --- a/Sources/web3swift/Web3/Web3+TxPool.swift +++ b/Sources/web3swift/Web3/Web3+TxPool.swift @@ -6,13 +6,9 @@ import Foundation import BigInt +import Core extension web3.TxPool { -// 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() return result diff --git a/Sources/web3swift/Web3/Web3+Utils.swift b/Sources/web3swift/Web3/Web3+Utils.swift index 4997c9426..0868d7c9e 100755 --- a/Sources/web3swift/Web3/Web3+Utils.swift +++ b/Sources/web3swift/Web3/Web3+Utils.swift @@ -7,6 +7,7 @@ import Foundation import BigInt import CryptoSwift +import Core public typealias Web3Utils = Web3.Utils @@ -24,7 +25,7 @@ extension Web3.Utils { public static func calculateContractAddress(from: EthereumAddress, nonce: BigUInt) -> EthereumAddress? { guard let normalizedAddress = from.addressData.setLengthLeft(32) else {return nil} guard let data = RLP.encode([normalizedAddress, nonce] as [AnyObject]) else {return nil} - guard let contractAddressData = Web3.Utils.sha3(data)?[12..<32] else {return nil} + guard let contractAddressData = Utilities.sha3(data)?[12..<32] else {return nil} guard let contractAddress = EthereumAddress(Data(contractAddressData)) else {return nil} return contractAddress } @@ -5889,315 +5890,3 @@ extension Web3.Utils { """ } - -extension Web3.Utils { - - /// Convert the private key (32 bytes of Data) to compressed (33 bytes) or non-compressed (65 bytes) public key. - public static func privateToPublic(_ privateKey: Data, compressed: Bool = false) -> Data? { - guard let publicKey = SECP256K1.privateToPublic(privateKey: privateKey, compressed: compressed) else {return nil} - return publicKey - } - - /// Convert a public key to the corresponding EthereumAddress. Accepts public keys in compressed (33 bytes), non-compressed (65 bytes) - /// or raw concat(X, Y) (64 bytes) format. - /// - /// Returns 20 bytes of address data. - public static func publicToAddressData(_ publicKey: Data) -> Data? { - if publicKey.count == 33 { - guard let decompressedKey = SECP256K1.combineSerializedPublicKeys(keys: [publicKey], outputCompressed: false) else {return nil} - return publicToAddressData(decompressedKey) - } - var stipped = publicKey - if (stipped.count == 65) { - if (stipped[0] != 4) { - return nil - } - stipped = stipped[1...64] - } - if (stipped.count != 64) { - return nil - } - let sha3 = stipped.sha3(.keccak256) - let addressData = sha3[12...31] - return addressData - } - - /// Convert a public key to the corresponding EthereumAddress. Accepts public keys in compressed (33 bytes), non-compressed (65 bytes) - /// or raw concat(X, Y) (64 bytes) format. - /// - /// Returns the EthereumAddress object. - public static func publicToAddress(_ publicKey: Data) -> EthereumAddress? { - guard let addressData = Web3.Utils.publicToAddressData(publicKey) else {return nil} - let address = addressData.toHexString().addHexPrefix().lowercased() - return EthereumAddress(address) - } - - /// Convert a public key to the corresponding EthereumAddress. Accepts public keys in compressed (33 bytes), non-compressed (65 bytes) - /// or raw concat(X, Y) (64 bytes) format. - /// - /// Returns a 0x prefixed hex string. - public static func publicToAddressString(_ publicKey: Data) -> String? { - guard let addressData = Web3.Utils.publicToAddressData(publicKey) else {return nil} - let address = addressData.toHexString().addHexPrefix().lowercased() - return address - } - - /// Converts address data (20 bytes) to the 0x prefixed hex string. Does not perform checksumming. - public static func addressDataToString(_ addressData: Data) -> String? { - guard addressData.count == 20 else {return nil} - return addressData.toHexString().addHexPrefix().lowercased() - } - - /// Hashes a personal message by first padding it with the "\u{19}Ethereum Signed Message:\n" string and message length string. - /// Should be used if some arbitrary information should be hashed and signed to prevent signing an Ethereum transaction - /// by accident. - public static func hashPersonalMessage(_ personalMessage: Data) -> Data? { - var prefix = "\u{19}Ethereum Signed Message:\n" - prefix += String(personalMessage.count) - guard let prefixData = prefix.data(using: .ascii) else {return nil} - var data = Data() - if personalMessage.count >= prefixData.count && prefixData == personalMessage[0 ..< prefixData.count] { - data.append(personalMessage) - } else { - data.append(prefixData) - data.append(personalMessage) - } - let hash = data.sha3(.keccak256) - return hash - } - - /// Parse a user-supplied string using the number of decimals for particular Ethereum unit. - /// If input is non-numeric or precision is not sufficient - returns nil. - /// Allowed decimal separators are ".", ",". - public static func parseToBigUInt(_ amount: String, units: Web3.Utils.Units = .eth) -> BigUInt? { - let unitDecimals = units.decimals - return parseToBigUInt(amount, decimals: unitDecimals) - } - - /// Parse a user-supplied string using the number of decimals. - /// If input is non-numeric or precision is not sufficient - returns nil. - /// Allowed decimal separators are ".", ",". - public static func parseToBigUInt(_ amount: String, decimals: Int = 18) -> BigUInt? { - let separators = CharacterSet(charactersIn: ".,") - let components = amount.trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: separators) - guard components.count == 1 || components.count == 2 else {return nil} - let unitDecimals = decimals - guard let beforeDecPoint = BigUInt(components[0], radix: 10) else {return nil} - var mainPart = beforeDecPoint*BigUInt(10).power(unitDecimals) - if (components.count == 2) { - let numDigits = components[1].count - guard numDigits <= unitDecimals else {return nil} - guard let afterDecPoint = BigUInt(components[1], radix: 10) else {return nil} - let extraPart = afterDecPoint*BigUInt(10).power(unitDecimals-numDigits) - mainPart = mainPart + extraPart - } - return mainPart - } - - /// Formats a BigInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", - /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. - /// - /// Returns nil of formatting is not possible to satisfy. - public static func formatToEthereumUnits(_ bigNumber: BigInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".") -> String? { - let magnitude = bigNumber.magnitude - guard let formatted = formatToEthereumUnits(magnitude, toUnits: toUnits, decimals: decimals, decimalSeparator: decimalSeparator) else {return nil} - switch bigNumber.sign { - case .plus: - return formatted - case .minus: - return "-" + formatted - } - } - - /// Formats a BigInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", - /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. - /// Fallbacks to scientific format if higher precision is required. - /// - /// Returns nil of formatting is not possible to satisfy. - public static func formatToPrecision(_ bigNumber: BigInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { - let magnitude = bigNumber.magnitude - guard let formatted = formatToPrecision(magnitude, numberDecimals: numberDecimals, formattingDecimals: formattingDecimals, decimalSeparator: decimalSeparator, fallbackToScientific: fallbackToScientific) else {return nil} - switch bigNumber.sign { - case .plus: - return formatted - case .minus: - return "-" + formatted - } - } - - /// Formats a BigUInt object to String. The supplied number is first divided into integer and decimal part based on "toUnits", - /// then limit the decimal part to "decimals" symbols and uses a "decimalSeparator" as a separator. - /// - /// Returns nil of formatting is not possible to satisfy. - public static func formatToEthereumUnits(_ bigNumber: BigUInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { - return formatToPrecision(bigNumber, numberDecimals: toUnits.decimals, formattingDecimals: decimals, decimalSeparator: decimalSeparator, fallbackToScientific: fallbackToScientific) - } - - /// Formats a BigUInt object to String. The supplied number is first divided into integer and decimal part based on "numberDecimals", - /// then limits the decimal part to "formattingDecimals" symbols and uses a "decimalSeparator" as a separator. - /// Fallbacks to scientific format if higher precision is required. - /// - /// Returns nil of formatting is not possible to satisfy. - public static func formatToPrecision(_ bigNumber: BigUInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? { - if bigNumber == 0 { - return "0" - } - let unitDecimals = numberDecimals - var toDecimals = formattingDecimals - if unitDecimals < toDecimals { - toDecimals = unitDecimals - } - let divisor = BigUInt(10).power(unitDecimals) - let (quotient, remainder) = bigNumber.quotientAndRemainder(dividingBy: divisor) - var fullRemainder = String(remainder) - let fullPaddedRemainder = fullRemainder.leftPadding(toLength: unitDecimals, withPad: "0") - let remainderPadded = fullPaddedRemainder[0.. formattingDecimals { - let end = firstDigit+1+formattingDecimals > fullPaddedRemainder.count ? fullPaddedRemainder.count: firstDigit+1+formattingDecimals - remainingDigits = String(fullPaddedRemainder[firstDigit+1 ..< end]) - } else { - remainingDigits = String(fullPaddedRemainder[firstDigit+1 ..< fullPaddedRemainder.count]) - } - if remainingDigits != "" { - fullRemainder = firstDecimalUnit + decimalSeparator + remainingDigits - } else { - fullRemainder = firstDecimalUnit - } - firstDigit = firstDigit + 1 - break - } - } - return fullRemainder + "e-" + String(firstDigit) - } - } - if (toDecimals == 0) { - return String(quotient) - } - return String(quotient) + decimalSeparator + remainderPadded - } - - /// Recover the Ethereum address from recoverable secp256k1 signature. Message is first hashed using the "personal hash" protocol. - /// BE WARNED - changing a message will result in different Ethereum address, but not in error. - /// - /// Input parameters should be hex Strings. - static public func personalECRecover(_ personalMessage: String, signature: String) -> EthereumAddress? { - guard let data = Data.fromHex(personalMessage) else {return nil} - guard let sig = Data.fromHex(signature) else {return nil} - return Web3.Utils.personalECRecover(data, signature: sig) - } - - /// Recover the Ethereum address from recoverable secp256k1 signature. Message is first hashed using the "personal hash" protocol. - /// BE WARNED - changing a message will result in different Ethereum address, but not in error. - /// - /// Input parameters should be Data objects. - static public func personalECRecover(_ personalMessage: Data, signature: Data) -> EthereumAddress? { - if signature.count != 65 { return nil} - let rData = signature[0..<32].bytes - let sData = signature[32..<64].bytes - var vData = signature[64] - if vData >= 27 && vData <= 30 { - vData -= 27 - } else if vData >= 31 && vData <= 34 { - vData -= 31 - } else if vData >= 35 && vData <= 38 { - vData -= 35 - } - - guard let signatureData = SECP256K1.marshalSignature(v: vData, r: rData, s: sData) else {return nil} - guard let hash = Web3.Utils.hashPersonalMessage(personalMessage) else {return nil} - guard let publicKey = SECP256K1.recoverPublicKey(hash: hash, signature: signatureData) else {return nil} - return Web3.Utils.publicToAddress(publicKey) - } - - - /// Recover the Ethereum address from recoverable secp256k1 signature. - /// Takes a hash of some message. What message is hashed should be checked by user separately. - /// - /// Input parameters should be Data objects. - static public func hashECRecover(hash: Data, signature: Data) -> EthereumAddress? { - if signature.count != 65 { return nil} - let rData = signature[0..<32].bytes - let sData = signature[32..<64].bytes - var vData = signature[64] - if vData >= 27 && vData <= 30 { - vData -= 27 - } else if vData >= 31 && vData <= 34 { - vData -= 31 - } else if vData >= 35 && vData <= 38 { - vData -= 35 - } - guard let signatureData = SECP256K1.marshalSignature(v: vData, r: rData, s: sData) else {return nil} - guard let publicKey = SECP256K1.recoverPublicKey(hash: hash, signature: signatureData) else {return nil} - return Web3.Utils.publicToAddress(publicKey) - } - - /// returns Ethereum variant of sha3 (keccak256) of data. Returns nil is data is empty - static public func keccak256(_ data: Data) -> Data? { - if data.count == 0 {return nil} - return data.sha3(.keccak256) - } - - /// returns Ethereum variant of sha3 (keccak256) of data. Returns nil is data is empty - static public func sha3(_ data: Data) -> Data? { - if data.count == 0 {return nil} - return data.sha3(.keccak256) - } - - /// returns sha256 of data. Returns nil is data is empty - static public func sha256(_ data: Data) -> Data? { - if data.count == 0 {return nil} - return data.sha256() - } - - /// Unmarshals a 65 byte recoverable EC signature into internal structure. - static func unmarshalSignature(signatureData: Data) -> SECP256K1.UnmarshaledSignature? { - if (signatureData.count != 65) {return nil} - let bytes = signatureData.bytes - let r = Array(bytes[0..<32]) - let s = Array(bytes[32..<64]) - return SECP256K1.UnmarshaledSignature(v: bytes[64], r: Data(r), s: Data(s)) - } - - /// Marshals the V, R and S signature parameters into a 65 byte recoverable EC signature. - static func marshalSignature(v: UInt8, r: [UInt8], s: [UInt8]) -> Data? { - guard r.count == 32, s.count == 32 else {return nil} - var completeSignature = Data(r) - completeSignature.append(Data(s)) - completeSignature.append(Data([v])) - return completeSignature - } - - /// Marshals internal signature structure into a 65 byte recoverable EC signature. - static func marshalSignature(unmarshalledSignature: SECP256K1.UnmarshaledSignature) -> Data { - var completeSignature = Data(unmarshalledSignature.r) - completeSignature.append(Data(unmarshalledSignature.s)) - completeSignature.append(Data([unmarshalledSignature.v])) - return completeSignature - } - - public static func hexToData(_ string: String) -> Data? { - return Data.fromHex(string) - } - - public static func hexToBigUInt(_ string: String) -> BigUInt? { - return BigUInt(string.stripHexPrefix(), radix: 16) - } - - public static func randomBytes(length: Int) -> Data? { - return Data.randomBytes(length: length) - } -} diff --git a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift index 67e6323ef..16815c3cb 100644 --- a/Sources/web3swift/Web3/Web3+WebsocketProvider.swift +++ b/Sources/web3swift/Web3/Web3+WebsocketProvider.swift @@ -9,6 +9,7 @@ import Starscream import BigInt import Foundation +import Core public protocol IWebsocketProvider { var socket: WebSocket {get} diff --git a/Sources/web3swift/Web3/Web3.swift b/Sources/web3swift/Web3/Web3.swift index 57315fec4..9477f2964 100755 --- a/Sources/web3swift/Web3/Web3.swift +++ b/Sources/web3swift/Web3/Web3.swift @@ -5,57 +5,7 @@ // import Foundation - -public enum Web3Error: Error { - case transactionSerializationError - case connectionError - - case dataError - case typeError - case valueError - case serverError(code: Int) - - case walletError - case inputError(desc: String) - case nodeError(desc: String) - case processingError(desc: String) - case keystoreError(err: AbstractKeystoreError) - case generalError(err: Error) - case unknownError - - - public var errorDescription: String { - switch self { - - case .transactionSerializationError: - return "Transaction Serialization Error" - case .connectionError: - return "Connection Error" - case .dataError: - return "Data Error" - case .walletError: - return "Wallet Error" - case .inputError(let desc): - return desc - case .nodeError(let desc): - return desc - case .processingError(let desc): - return desc - case .keystoreError(let err): - return err.localizedDescription - case .generalError(let err): - return err.localizedDescription - case .unknownError: - return "Unknown Error" - case .typeError: - return "Unsupported type" - case let .serverError(code: code): - return "Server error: \(code)" - case .valueError: - return "You're passing value that doesn't supported by this method." - } - } -} +import Core /// An arbitary Web3 object. Is used only to construct provider bound fully functional object by either supplying provider URL /// or using pre-coded Infura nodes diff --git a/Tests/web3swiftTests/localTests/ABIEncoderSoliditySha3Test.swift b/Tests/web3swiftTests/localTests/ABIEncoderSoliditySha3Test.swift index 5d59d356e..32a756047 100644 --- a/Tests/web3swiftTests/localTests/ABIEncoderSoliditySha3Test.swift +++ b/Tests/web3swiftTests/localTests/ABIEncoderSoliditySha3Test.swift @@ -8,6 +8,7 @@ import Foundation import XCTest +import Core @testable import web3swift class ABIEncoderSoliditySha3Test: LocalTestCase { diff --git a/Tests/web3swiftTests/localTests/DataConversionTests.swift b/Tests/web3swiftTests/localTests/DataConversionTests.swift index a0f43dc29..a13f207d3 100644 --- a/Tests/web3swiftTests/localTests/DataConversionTests.swift +++ b/Tests/web3swiftTests/localTests/DataConversionTests.swift @@ -1,4 +1,4 @@ -// Package: web3swift +// // Created by Alex Vlasov. // Copyright © 2018 Alex Vlasov. All rights reserved. // @@ -6,6 +6,7 @@ // import XCTest +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift b/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift index b56a40f42..f9714360f 100644 --- a/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift +++ b/Tests/web3swiftTests/localTests/EIP1559BlockTests.swift @@ -4,6 +4,9 @@ import BigInt @testable import web3swift +@testable +import Core + class EIP1559BlockTests: LocalTestCase { let uselessBlockPart = ( number: BigUInt(12_965_000), diff --git a/Tests/web3swiftTests/localTests/EIP712Tests.swift b/Tests/web3swiftTests/localTests/EIP712Tests.swift index f5a323d8f..d6e7c6d02 100644 --- a/Tests/web3swiftTests/localTests/EIP712Tests.swift +++ b/Tests/web3swiftTests/localTests/EIP712Tests.swift @@ -1,4 +1,5 @@ import XCTest +import Core @testable import web3swift class EIP712Tests: LocalTestCase { diff --git a/Tests/web3swiftTests/localTests/LocalTestCase.swift b/Tests/web3swiftTests/localTests/LocalTestCase.swift index ed13c1f91..00a2f797c 100644 --- a/Tests/web3swiftTests/localTests/LocalTestCase.swift +++ b/Tests/web3swiftTests/localTests/LocalTestCase.swift @@ -1,6 +1,7 @@ import Foundation import XCTest import BigInt +import Core import web3swift @@ -28,7 +29,7 @@ class LocalTestCase: XCTestCase { 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) + let value = Utilities.parseToBigUInt("1.0", units: .eth) let from = allAddresses[0] let writeTX = contract!.write("fallback")! diff --git a/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift b/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift index fbaf23280..20195f6b4 100755 --- a/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftAdvancedABIv2Tests.swift @@ -7,6 +7,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift index ca3d2cce7..a0bae7685 100755 --- a/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftBasicLocalNodeTests.swift @@ -9,6 +9,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift @@ -57,7 +58,7 @@ class web3swiftBasicLocalNodeTests: XCTestCase { let parameters = [] as [AnyObject] let sendTx = contract.method("fallback", parameters: parameters)! - let valueToSend = Web3.Utils.parseToBigUInt("1.0", units: .eth) + let valueToSend = Utilities.parseToBigUInt("1.0", units: .eth) sendTx.transactionOptions.value = valueToSend sendTx.transactionOptions.from = allAddresses[0] @@ -95,79 +96,4 @@ class web3swiftBasicLocalNodeTests: XCTestCase { let txnGasPrice = details.transaction.parameters.gasPrice ?? 0 XCTAssert(balanceBeforeFrom - (balanceAfterFrom + receipt.gasUsed * txnGasPrice) == valueToSend) } - - // FIXME: Crashes on CI/CD - // 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.ownedAccounts() - - // let response = try web3.personal.signPersonalMessage(message: "hello world".data(using: .utf8)!, from: allAddresses[0]) - - // XCTAssert(response.toHexString() == "b686c8ddc854bd49de9eb62eb4e52af4c69a89802b40fe9a295e346b111406393c6e3f05114561ab845a47196ad22c33cec67592af9a9e42bfc067a20c7d4b6101") - // } - - // 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.ownedAccounts() -// -// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! -// let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! -// -// let parameters = [] as [AnyObject] -// let sendTx = contract.method("fallback", parameters: parameters)! -// -// let valueToSend = Web3.Utils.parseToBigUInt("1.0", units: .eth) -// sendTx.transactionOptions.value = valueToSend -// sendTx.transactionOptions.from = allAddresses[0] -// -// let _ = try sendTx.sendPromise() -// -// let result = try web3.txPool.getStatus() -// -// print(result) -// } -// -// func testTxPoolInspect() throws { -// let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) -// let allAddresses = try web3.eth.ownedAccounts() -// -// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! -// let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! -// -// let parameters = [] as [AnyObject] -// let sendTx = contract.method("fallback", parameters: parameters)! -// -// let valueToSend = Web3.Utils.parseToBigUInt("1.0", units: .eth) -// sendTx.transactionOptions.value = valueToSend -// sendTx.transactionOptions.from = allAddresses[0] -// -// let _ = try sendTx.sendPromise() -// -// let result = try web3.txPool.getInspect() -// -// print(result) -// } -// -// func testTxPoolContent() throws { -// let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) -// let allAddresses = try web3.eth.ownedAccounts() -// -// let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! -// let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2)! -// -// let parameters = [] as [AnyObject] -// let sendTx = contract.method("fallback", parameters: parameters)! -// -// let valueToSend = Web3.Utils.parseToBigUInt("1.0", units: .eth) -// sendTx.transactionOptions.value = valueToSend -// sendTx.transactionOptions.from = allAddresses[0] -// -// let _ = try sendTx.sendPromise() -// -// let result = try web3.txPool.getContent() -// -// print(result) -// } } diff --git a/Tests/web3swiftTests/localTests/web3swiftDecodeSolidityErrorType.swift b/Tests/web3swiftTests/localTests/web3swiftDecodeSolidityErrorType.swift index 6082af7ef..1d1fac01f 100644 --- a/Tests/web3swiftTests/localTests/web3swiftDecodeSolidityErrorType.swift +++ b/Tests/web3swiftTests/localTests/web3swiftDecodeSolidityErrorType.swift @@ -8,6 +8,7 @@ import XCTest import web3swift +import Core /// Since solidity 0.8.4 a new type was introduced called `error`. /// Contracts' ABI with this type were not decodable. diff --git a/Tests/web3swiftTests/localTests/web3swiftEIP67Tests.swift b/Tests/web3swiftTests/localTests/web3swiftEIP67Tests.swift index 722bd0ed6..84cb73d3a 100755 --- a/Tests/web3swiftTests/localTests/web3swiftEIP67Tests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftEIP67Tests.swift @@ -7,6 +7,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftEIP681Tests.swift b/Tests/web3swiftTests/localTests/web3swiftEIP681Tests.swift index 90ec4f233..a4aa2085f 100755 --- a/Tests/web3swiftTests/localTests/web3swiftEIP681Tests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftEIP681Tests.swift @@ -5,6 +5,7 @@ // import XCTest +import Core @testable import web3swift class web3swiftEIP681Tests: XCTestCase { diff --git a/Tests/web3swiftTests/localTests/web3swiftERC20ClassTests.swift b/Tests/web3swiftTests/localTests/web3swiftERC20ClassTests.swift index 70818ad8a..d6047539c 100755 --- a/Tests/web3swiftTests/localTests/web3swiftERC20ClassTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftERC20ClassTests.swift @@ -6,6 +6,7 @@ import XCTest import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftERC20Tests.swift b/Tests/web3swiftTests/localTests/web3swiftERC20Tests.swift index e8e4514c7..e923eebb5 100755 --- a/Tests/web3swiftTests/localTests/web3swiftERC20Tests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftERC20Tests.swift @@ -6,6 +6,7 @@ import XCTest import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift b/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift index d9e76d9bf..4127994aa 100755 --- a/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftEventloopTests.swift @@ -5,6 +5,7 @@ // import XCTest +import Core @testable import web3swift //TODO: refactor me @@ -35,35 +36,6 @@ class web3swiftEventloopTests: XCTestCase { await waitForExpectations(timeout: 60, handler: nil) } - // func testNonceMiddleware() throws { - // let web3 = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!) - // let middleware = Web3.Utils.NonceMiddleware() - // middleware.attach(web3) - - // let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! - // let ksData = getKeystoreData() - // FIXME: Ganache crash here - // let tempKeystore = EthereumKeystoreV3(ksData!) - // let keystoreManager = KeystoreManager([tempKeystore!]) - // web3.addKeystoreManager(keystoreManager) - - // var tx = web3.eth.sendETH(to: sendToAddress, amount: 1000) - // tx!.transactionOptions.from = tempKeystore!.addresses!.first! - // var result = try! tx!.send(password: "web3swift") - // let newNonce = result.transaction.nonce - // sleep(1) - // let hookNewNonce = middleware.nonceLookups[tempKeystore!.addresses!.first!]! - // XCTAssertEqual(newNonce, hookNewNonce) - - // tx = web3.eth.sendETH(to: sendToAddress, amount: 1000) - // tx!.transactionOptions.from = tempKeystore!.addresses!.first! - // result = try! tx!.send(password: "web3swift") - // sleep(1) - // let newNonce2 = result.transaction.nonce - // let hookNewNonce2 = middleware.nonceLookups[tempKeystore!.addresses!.first!]! - // XCTAssert(newNonce2 == hookNewNonce2) - // } - func getKeystoreData() -> Data? { let bundle = Bundle(for: type(of: self)) guard let path = bundle.path(forResource: "key", ofType: "json") else {return nil} diff --git a/Tests/web3swiftTests/localTests/web3swiftHelpers.swift b/Tests/web3swiftTests/localTests/web3swiftHelpers.swift index 71864fe9d..f56a9daca 100644 --- a/Tests/web3swiftTests/localTests/web3swiftHelpers.swift +++ b/Tests/web3swiftTests/localTests/web3swiftHelpers.swift @@ -8,6 +8,7 @@ import Foundation import BigInt +import Core import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftKeystoresTests.swift b/Tests/web3swiftTests/localTests/web3swiftKeystoresTests.swift index 05c22e6b1..c518e662b 100755 --- a/Tests/web3swiftTests/localTests/web3swiftKeystoresTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftKeystoresTests.swift @@ -6,6 +6,7 @@ import XCTest import CryptoSwift +import Core @testable import web3swift @@ -131,7 +132,7 @@ class web3swiftKeystoresTests: LocalTestCase { XCTAssertNotNil(keystore) let account = keystore!.addresses![0] let key = try! keystore!.UNSAFE_getPrivateKeyData(password: "", account: account) - let pubKey = Web3.Utils.privateToPublic(key, compressed: true) + let pubKey = Utilities.privateToPublic(key, compressed: true) XCTAssert(pubKey?.toHexString() == "027160bd3a4d938cac609ff3a11fe9233de7b76c22a80d2b575e202cbf26631659") } @@ -147,7 +148,7 @@ class web3swiftKeystoresTests: LocalTestCase { XCTAssertNotNil(keystore) let account = keystore!.addresses![0] let key = try! keystore!.UNSAFE_getPrivateKeyData(password: "", account: account) - let pubKey = Web3.Utils.privateToPublic(key, compressed: true) + let pubKey = Utilities.privateToPublic(key, compressed: true) XCTAssert(pubKey?.toHexString() == "027160bd3a4d938cac609ff3a11fe9233de7b76c22a80d2b575e202cbf26631659") } diff --git a/Tests/web3swiftTests/localTests/web3swiftNumberFormattingUtilTests.swift b/Tests/web3swiftTests/localTests/web3swiftNumberFormattingUtilTests.swift index 1282a6f09..bd6e11a0e 100755 --- a/Tests/web3swiftTests/localTests/web3swiftNumberFormattingUtilTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftNumberFormattingUtilTests.swift @@ -7,6 +7,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift @@ -15,55 +16,55 @@ class web3swiftNumberFormattingUtilTests: LocalTestCase { func testNumberFormattingUtil() throws { let balance = BigInt("-1000000000000000000") print("this is print") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") XCTAssert(formatted == "-1") } func testNumberFormattingUtil2() throws { let balance = BigInt("-1000000000000000") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") XCTAssert(formatted == "-0,0010") } func testNumberFormattingUtil3() throws { let balance = BigInt("-1000000000000") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") XCTAssert(formatted == "-0,0000") } func testNumberFormattingUtil4() throws { let balance = BigInt("-1000000000000") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",") XCTAssert(formatted == "-0,000001000") } func testNumberFormattingUtil5() throws { let balance = BigInt("-1") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",", fallbackToScientific: true) + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",", fallbackToScientific: true) XCTAssert(formatted == "-1e-18") } func testNumberFormattingUtil6() throws { let balance = BigInt("0") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",") XCTAssert(formatted == "0") } func testNumberFormattingUtil7() throws { let balance = BigInt("-1100000000000000000") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",") XCTAssert(formatted == "-1,1000") } func testNumberFormattingUtil8() throws { let balance = BigInt("100") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",", fallbackToScientific: true) + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",", fallbackToScientific: true) XCTAssert(formatted == "1,00e-16") } func testNumberFormattingUtil9() throws { let balance = BigInt("1000000") - let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",", fallbackToScientific: true) + let formatted = Utilities.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",", fallbackToScientific: true) XCTAssert(formatted == "1,0000e-12") } diff --git a/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift b/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift index 697cbc422..de10650bf 100755 --- a/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftPersonalSignatureTests.swift @@ -7,6 +7,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift @@ -25,7 +26,7 @@ class web3swiftPersonalSignatureTests: XCTestCase { print("V = " + String(unmarshalledSignature.v)) print("R = " + Data(unmarshalledSignature.r).toHexString()) print("S = " + Data(unmarshalledSignature.s).toHexString()) - print("Personal hash = " + Web3.Utils.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString()) + print("Personal hash = " + Utilities.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString()) let signer = try web3.personal.ecrecover(personalMessage: message.data(using: .utf8)!, signature: signature) XCTAssert(expectedAddress == signer, "Failed to sign personal message") } @@ -70,7 +71,7 @@ class web3swiftPersonalSignatureTests: XCTestCase { print("V = " + String(unmarshalledSignature.v)) print("R = " + Data(unmarshalledSignature.r).toHexString()) print("S = " + Data(unmarshalledSignature.s).toHexString()) - print("Personal hash = " + Web3.Utils.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString()) + print("Personal hash = " + Utilities.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString()) // Calling contract contract = web3.contract(abiString, at: receipt.contractAddress!)! @@ -78,7 +79,7 @@ class web3swiftPersonalSignatureTests: XCTestCase { tx?.transactionOptions.from = expectedAddress var result = try await tx!.call() guard let hash = result["hash"]! as? Data else {return XCTFail()} - XCTAssert(Web3.Utils.hashPersonalMessage(message.data(using: .utf8)!)! == hash) + XCTAssert(Utilities.hashPersonalMessage(message.data(using: .utf8)!)! == hash) tx = contract.read("recoverSigner", parameters: [message, unmarshalledSignature.v, Data(unmarshalledSignature.r), Data(unmarshalledSignature.s)] as [AnyObject]) tx?.transactionOptions.from = expectedAddress diff --git a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift index de4c79512..6cc79ab3c 100755 --- a/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftPromisesTests.swift @@ -4,12 +4,9 @@ // Copyright © 2018 Alex Vlasov. All rights reserved. // -// TODO: Replace `XCTAssert` with more explicite `XCTAssertEqual`, where Applicable - import XCTest - +import Core import BigInt -//import EthereumAddress @testable import web3swift @@ -21,21 +18,6 @@ class web3swiftPromisesTests: XCTestCase { let balance = try await web3.eth.getBalance(for: "0xe22b8979739D724343bd002F9f432F5990879901") print(balance) } - // 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")!) @@ -46,10 +28,10 @@ class web3swiftPromisesTests: XCTestCase { let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress, abiVersion: 2) guard let writeTX = contract?.write("fallback") else {return XCTFail()} writeTX.transactionOptions.from = tempKeystore!.addresses?.first - writeTX.transactionOptions.value = BigUInt("1.0", .eth) + writeTX.transactionOptions.value = BigUInt("1.0", Utilities.Units.eth) let estimate = try await writeTX.estimateGas(with: nil) print(estimate) - XCTAssert(estimate == 21000) + XCTAssertEqual(estimate, 21000) } func testEstimateGasFixPromise() async throws { @@ -95,7 +77,7 @@ class web3swiftPromisesTests: XCTestCase { let fromAddress = tempKeystore!.addresses?.first options.from = fromAddress - let amount1 = Web3.Utils.parseToBigUInt("0.000000000000000001", units: .eth) // 1 wei + let amount1 = Utilities.parseToBigUInt("0.000000000000000001", units: Utilities.Units.eth) // 1 wei guard let tx1 = contract.write("test", parameters: [amount1] as [AnyObject], @@ -106,7 +88,7 @@ class web3swiftPromisesTests: XCTestCase { let estimate1 = try await tx1.estimateGas(with: nil) print(estimate1) - let amount2 = Web3.Utils.parseToBigUInt("0.00000005", units: .eth) // 50 gwei + let amount2 = Utilities.parseToBigUInt("0.00000005", units: .eth) // 50 gwei guard let tx2 = contract.write("test", parameters: [amount2] as [AnyObject], extraData: Data(), @@ -115,7 +97,7 @@ class web3swiftPromisesTests: XCTestCase { } let estimate2 = try await tx2.estimateGas(with: nil) print(estimate2) - XCTAssert(estimate2 - estimate1 <= 22000) + XCTAssertLessThanOrEqual(estimate2 - estimate1, 22000) } // FIXME: Temporary deleted method `sendETH` should be restored. // func testSendETHPromise() async throws { diff --git a/Tests/web3swiftTests/localTests/web3swiftRLPTests.swift b/Tests/web3swiftTests/localTests/web3swiftRLPTests.swift index 2f28d5e11..f89532405 100755 --- a/Tests/web3swiftTests/localTests/web3swiftRLPTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftRLPTests.swift @@ -6,6 +6,7 @@ import XCTest import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/localTests/web3swiftTests.swift b/Tests/web3swiftTests/localTests/web3swiftTests.swift index 131bf98d5..aa955bd34 100755 --- a/Tests/web3swiftTests/localTests/web3swiftTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftTests.swift @@ -8,6 +8,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift @@ -23,12 +24,12 @@ class web3swiftTests: XCTestCase { func testCombiningPublicKeys() throws { let priv1 = Data(repeating: 0x01, count: 32) - let pub1 = Web3.Utils.privateToPublic(priv1, compressed: true)! + let pub1 = Utilities.privateToPublic(priv1, compressed: true)! let priv2 = Data(repeating: 0x02, count: 32) - let pub2 = Web3.Utils.privateToPublic(priv2, compressed: true)! + let pub2 = Utilities.privateToPublic(priv2, compressed: true)! let combined = SECP256K1.combineSerializedPublicKeys(keys: [pub1, pub2], outputCompressed: true) let compinedPriv = Data(repeating: 0x03, count: 32) - let compinedPub = Web3.Utils.privateToPublic(compinedPriv, compressed: true) + let compinedPub = Utilities.privateToPublic(compinedPriv, compressed: true) XCTAssert(compinedPub == combined) } diff --git a/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift b/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift index 3d79ea29e..baa00a2c3 100755 --- a/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift +++ b/Tests/web3swiftTests/localTests/web3swiftTransactionsTests.swift @@ -8,6 +8,7 @@ import Foundation import XCTest import CryptoSwift import BigInt +import Core // swiftlint:disable file_length // swiftlint:disable type_body_length @@ -606,8 +607,8 @@ class web3swiftTransactionsTests: XCTestCase { nonce: 9, value: 1000000000000000000, data: Data(), v: 0, r: 0, s: 0, parameters: params) let privateKeyData = Data.fromHex("0x4646464646464646464646464646464646464646464646464646464646464646")! - let publicKey = Web3.Utils.privateToPublic(privateKeyData, compressed: false) - let sender = Web3.Utils.publicToAddress(publicKey!) + let publicKey = Utilities.privateToPublic(privateKeyData, compressed: false) + let sender = Utilities.publicToAddress(publicKey!) transaction.chainID = 1 print(transaction) let hash = transaction.hashForSignature() @@ -629,7 +630,7 @@ class web3swiftTransactionsTests: XCTestCase { let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! 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 value = Utilities.parseToBigUInt("1.0", units: .eth) let from = allAddresses[0] let writeTX = contract!.write("fallback")! writeTX.transactionOptions.from = from diff --git a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift index 2c66add50..4a43763bf 100755 --- a/Tests/web3swiftTests/localTests/web3swiftUserCases.swift +++ b/Tests/web3swiftTests/localTests/web3swiftUserCases.swift @@ -6,7 +6,7 @@ import XCTest import BigInt -//import EthereumAddress +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/remoteTests/ENSTests.swift b/Tests/web3swiftTests/remoteTests/ENSTests.swift index 8d40c0f0e..e10e4ccab 100755 --- a/Tests/web3swiftTests/remoteTests/ENSTests.swift +++ b/Tests/web3swiftTests/remoteTests/ENSTests.swift @@ -5,6 +5,7 @@ // import XCTest +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift index 105c19562..709e9ed7d 100644 --- a/Tests/web3swiftTests/remoteTests/GasOracleTests.swift +++ b/Tests/web3swiftTests/remoteTests/GasOracleTests.swift @@ -7,6 +7,7 @@ import XCTest import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/remoteTests/InfuraTests.swift b/Tests/web3swiftTests/remoteTests/InfuraTests.swift index 870cd6ea5..b9d5ece71 100755 --- a/Tests/web3swiftTests/remoteTests/InfuraTests.swift +++ b/Tests/web3swiftTests/remoteTests/InfuraTests.swift @@ -5,6 +5,7 @@ // import XCTest +import Core @testable import web3swift @@ -16,7 +17,7 @@ class InfuraTests: XCTestCase { let web3 = await Web3.InfuraMainnetWeb3(accessToken: Constants.infuraToken) let address = EthereumAddress("0xd61b5ca425F8C8775882d4defefC68A6979DBbce")! let balance = try await web3.eth.getBalance(for: address) - let balString = Web3.Utils.formatToEthereumUnits(balance, toUnits: .eth, decimals: 3) + let balString = Utilities.formatToEthereumUnits(balance, toUnits: .eth, decimals: 3) print(balString!) } catch { XCTFail() diff --git a/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift b/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift index a6cdd5ca4..6c8f6fe7a 100755 --- a/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift +++ b/Tests/web3swiftTests/remoteTests/RemoteParsingTests.swift @@ -7,6 +7,7 @@ import XCTest import CryptoSwift import BigInt +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift b/Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift index e56571eaa..1e435bcb5 100644 --- a/Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift +++ b/Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift @@ -7,6 +7,8 @@ // import XCTest import BigInt +import web3swift +import Core @testable import web3swift diff --git a/Tests/web3swiftTests/remoteTests/WebsocketTests.swift b/Tests/web3swiftTests/remoteTests/WebsocketTests.swift index 91b7a13b6..dc3d0de92 100644 --- a/Tests/web3swiftTests/remoteTests/WebsocketTests.swift +++ b/Tests/web3swiftTests/remoteTests/WebsocketTests.swift @@ -7,6 +7,7 @@ // import XCTest import Starscream +import Core @testable import web3swift