Skip to content

Commit 7b3e396

Browse files
Merge branch 'develop-upstream' into hot-fix/data-to-hex-string
# Conflicts: # Sources/Core/EthereumNetwork/Request/APIRequest+Methods.swift
2 parents 2588e6a + 7dee353 commit 7b3e396

File tree

4 files changed

+104
-19
lines changed

4 files changed

+104
-19
lines changed

Sources/Core/Contract/ContractProtocol.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ extension DefaultContractProtocol {
225225
let parameters = parameters,
226226
!parameters.isEmpty {
227227
guard constructor.inputs.count == parameters.count,
228-
// FIXME: This should be zipped, because Arrays don't guarantee it's elements order
229228
let encodedData = constructor.encodeParameters(parameters) else {
230229
NSLog("Constructor encoding will fail as the number of input arguments doesn't match the number of given arguments.")
231230
return nil

Sources/Core/EthereumABI/ABIEncoding.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ extension ABIEncoder {
137137
/// - values: Contract values of a given element to encode
138138
/// - Returns: Encoded data
139139
public static func encode(types: [ABI.Element.InOut], values: [AnyObject]) -> Data? {
140-
// FIXME: This should be zipped, because Arrays don't guarantee it's elements order
141140
guard types.count == values.count else {return nil}
142141
let params = types.compactMap { (el) -> ABI.Element.ParameterType in
143142
return el.type
@@ -152,7 +151,6 @@ extension ABIEncoder {
152151
/// - values: Contract values of a given element to encode
153152
/// - Returns: Encoded data
154153
public static func encode(types: [ABI.Element.ParameterType], values: [AnyObject]) -> Data? {
155-
// FIXME: This should be zipped, because Arrays don't guarantee it's elements order
156154
guard types.count == values.count else {return nil}
157155
var tails = [Data]()
158156
var heads = [Data]()

Sources/Core/EthereumNetwork/Request/APIRequest+Methods.swift

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,25 @@ extension APIRequest {
3333
throw Web3Error.serverError(code: response.statusCode)
3434
}
3535
}
36-
36+
37+
if let error = (try? JSONDecoder().decode(JsonRpcErrorObject.self, from: data))?.error {
38+
guard let parsedErrorCode = error.parsedErrorCode else {
39+
throw Web3Error.nodeError(desc: "\(error.message)\nError code: \(error.code)")
40+
}
41+
let description = "\(parsedErrorCode.errorName). Error code: \(error.code). \(error.message)"
42+
switch parsedErrorCode {
43+
case .parseError, .invalidParams:
44+
throw Web3Error.inputError(desc: description)
45+
case .methodNotFound, .invalidRequest:
46+
throw Web3Error.processingError(desc: description)
47+
case .internalError, .serverError:
48+
throw Web3Error.nodeError(desc: description)
49+
}
50+
}
51+
3752
/// This bit of code is purposed to work with literal types that comes in ``Response`` in hexString type.
3853
/// Currently it's just `Data` and any kind of Integers `(U)Int`, `Big(U)Int`.
39-
if Result.self == Data.self || Result.self == UInt.self || Result.self == Int.self || Result.self == BigInt.self || Result.self == BigUInt.self {
40-
guard let LiteralType = Result.self as? LiteralInitiableFromString.Type else { throw Web3Error.typeError }
54+
if let LiteralType = Result.self as? LiteralInitiableFromString.Type {
4155
guard let responseAsString = try? JSONDecoder().decode(APIResponse<String>.self, from: data) else { throw Web3Error.dataError }
4256
guard let literalValue = LiteralType.init(from: responseAsString.result) else { throw Web3Error.dataError }
4357
/// `literalValue` conforms `LiteralInitiableFromString`, that conforming to an `APIResponseType` type, so it's never fails.
@@ -47,3 +61,76 @@ extension APIRequest {
4761
return try JSONDecoder().decode(APIResponse<Result>.self, from: data)
4862
}
4963
}
64+
65+
/// JSON RPC Error object. See official specification https://www.jsonrpc.org/specification#error_object
66+
fileprivate struct JsonRpcErrorObject: Decodable {
67+
public let error: RpcError?
68+
69+
class RpcError: Decodable {
70+
let message: String
71+
let code: Int
72+
var parsedErrorCode: JsonRpcErrorCode? {
73+
JsonRpcErrorCode.from(code)
74+
}
75+
}
76+
}
77+
78+
/// For error codes specification see chapter `5.1 Error object`
79+
/// https://www.jsonrpc.org/specification#error_object
80+
fileprivate enum JsonRpcErrorCode {
81+
/// -32700
82+
/// Invalid JSON was received by the server. An error occurred on the server while parsing the JSON
83+
case parseError
84+
/// -32600
85+
/// The JSON sent is not a valid Request object.
86+
case invalidRequest
87+
/// -32601
88+
/// The method does not exist / is not available.
89+
case methodNotFound
90+
/// -32602
91+
/// Invalid method parameter(s).
92+
case invalidParams
93+
/// -32603
94+
/// Internal JSON-RPC error.
95+
case internalError
96+
/// Values in range of -32000 to -32099
97+
/// Reserved for implementation-defined server-errors.
98+
case serverError(Int)
99+
100+
var errorName: String {
101+
switch self {
102+
case .parseError:
103+
return "Parsing error"
104+
case .invalidRequest:
105+
return "Invalid request"
106+
case .methodNotFound:
107+
return "Method not found"
108+
case .invalidParams:
109+
return "Invalid parameters"
110+
case .internalError:
111+
return "Internal error"
112+
case .serverError(_):
113+
return "Server error"
114+
}
115+
}
116+
117+
static func from(_ code: Int) -> JsonRpcErrorCode? {
118+
switch code {
119+
case -32700:
120+
return .parseError
121+
case -32600:
122+
return .invalidRequest
123+
case -32601:
124+
return .methodNotFound
125+
case -32602:
126+
return .invalidParams
127+
case -32603:
128+
return .internalError
129+
default:
130+
if (-32099)...(-32000) ~= code {
131+
return .serverError(code)
132+
}
133+
return nil
134+
}
135+
}
136+
}

Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import Core
1616
class ST20AndSecurityTokenTests: XCTestCase {
1717

1818
func testERC20TokenCreation() async throws {
19-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
20-
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
19+
let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
20+
let w3sTokenAddress = EthereumAddress("0x33d191db2486e0d245b44fde3fae5ed667d5694b")!
2121
let st20token = ST20.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
2222
try await st20token.readProperties()
2323
XCTAssertEqual(st20token.symbol(), "MIMI")
@@ -26,7 +26,7 @@ class ST20AndSecurityTokenTests: XCTestCase {
2626
}
2727

2828
func testST20tokenBalanceAndAllowance() async throws {
29-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
29+
let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
3030
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
3131
let st20token = ST20.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
3232
let userAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")!
@@ -37,20 +37,21 @@ class ST20AndSecurityTokenTests: XCTestCase {
3737
}
3838

3939
func testSecurityTokenInvestors() async throws {
40-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
40+
let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
4141
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
4242
let stoken = SecurityToken.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
4343
let investorsCount = try await stoken.investorCount()
4444
let stringInvestorsCount = String(investorsCount)
4545
XCTAssertEqual(stringInvestorsCount, "0")
4646
}
47-
48-
func testSecurityTokenGranularity() async throws {
49-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
50-
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
51-
let stoken = SecurityToken.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
52-
let granularity = try await stoken.getGranularity()
53-
let stringGranularity = String(granularity)
54-
XCTAssertEqual(stringGranularity, "1000000000000000000")
55-
}
47+
48+
// FIXME: Enable me back again
49+
// func testSecurityTokenGranularity() async throws {
50+
// let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
51+
// let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
52+
// let stoken = SecurityToken.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
53+
// let granularity = try await stoken.getGranularity()
54+
// let stringGranularity = String(granularity)
55+
// XCTAssertEqual(stringGranularity, "1000000000000000000")
56+
// }
5657
}

0 commit comments

Comments
 (0)