Skip to content

Commit 4bd644a

Browse files
Merge branch 'develop' into master
2 parents 45f2a70 + 860c68e commit 4bd644a

File tree

3 files changed

+118
-25
lines changed

3 files changed

+118
-25
lines changed

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

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,24 @@ extension APIRequest {
3434
}
3535
}
3636

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 (-32000)...(-32099) ~= code {
131+
return .serverError(code)
132+
}
133+
return nil
134+
}
135+
}
136+
}

Sources/web3swift/Web3/Web3.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,21 @@ extension Web3 {
3333
}
3434

3535
/// Initialized Web3 instance bound to Infura's rinkeby provider.
36+
@available(*, deprecated, message: "This network support was deprecated by Infura")
3637
public static func InfuraRinkebyWeb3(accessToken: String? = nil) async -> Web3 {
3738
let infura = await InfuraProvider(Networks.Rinkeby, accessToken: accessToken)!
3839
return Web3(provider: infura)
3940
}
4041

4142
/// Initialized Web3 instance bound to Infura's ropsten provider.
43+
@available(*, deprecated, message: "This network support was deprecated by Infura")
4244
public static func InfuraRopstenWeb3(accessToken: String? = nil) async -> Web3 {
4345
let infura = await InfuraProvider(Networks.Ropsten, accessToken: accessToken)!
4446
return Web3(provider: infura)
4547
}
4648

4749
/// Initialized Web3 instance bound to Infura's kovan provider.
50+
@available(*, deprecated, message: "This network support was deprecated by Infura")
4851
public static func InfuraKovanWeb3(accessToken: String? = nil) async -> Web3 {
4952
let infura = await InfuraProvider(Networks.Kovan, accessToken: accessToken)!
5053
return Web3(provider: infura)

Tests/web3swiftTests/remoteTests/ST20AndSecurityTokenTests.swift

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,45 @@ import Core
1515
// MARK: Works only with network connection
1616
class ST20AndSecurityTokenTests: XCTestCase {
1717

18-
func testERC20TokenCreation() async throws {
19-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
20-
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
21-
let st20token = ST20.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
22-
try await st20token.readProperties()
23-
XCTAssertEqual(st20token.symbol(), "MIMI")
24-
XCTAssertEqual(st20token.name(), "Mimi")
25-
XCTAssertEqual(st20token.decimals(), 18)
26-
}
18+
// FIXME: Enable me back again
19+
// Test fails because there's no such wallet on goerli chain as well as token.
20+
// func testERC20TokenCreation() async throws {
21+
// let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
22+
// let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
23+
// let st20token = ST20.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
24+
// try await st20token.readProperties()
25+
// XCTAssertEqual(st20token.symbol(), "MIMI")
26+
// XCTAssertEqual(st20token.name(), "Mimi")
27+
// XCTAssertEqual(st20token.decimals(), 18)
28+
// }
2729

2830
func testST20tokenBalanceAndAllowance() async throws {
29-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
31+
let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
3032
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
3133
let st20token = ST20.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
3234
let userAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")!
3335
let balance = try await st20token.getBalance(account: userAddress)
3436
let allowance = try await st20token.getAllowance(originalOwner: userAddress, delegate: userAddress)
35-
XCTAssertEqual(String(balance), "0")
37+
XCTAssertEqual(balance, 0)
3638
XCTAssertEqual(allowance, 0)
3739
}
3840

3941
func testSecurityTokenInvestors() async throws {
40-
let web3 = await Web3.InfuraKovanWeb3(accessToken: Constants.infuraToken)
42+
let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
4143
let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
4244
let stoken = SecurityToken.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
4345
let investorsCount = try await stoken.investorCount()
44-
let stringInvestorsCount = String(investorsCount)
45-
XCTAssertEqual(stringInvestorsCount, "0")
46-
}
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")
46+
XCTAssertEqual(investorsCount, 0)
5547
}
48+
49+
// FIXME: Enable me back again
50+
// Test fails because there's no such wallet on goerli chain as well as token.
51+
// func testSecurityTokenGranularity() async throws {
52+
// let web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken)
53+
// let w3sTokenAddress = EthereumAddress("0x2dD33957C90880bE4Ee9fd5F703110BDA2E579EC")!
54+
// let stoken = SecurityToken.init(web3: web3, provider: web3.provider, address: w3sTokenAddress)
55+
// let granularity = try await stoken.getGranularity()
56+
// let stringGranularity = String(granularity)
57+
// XCTAssertEqual(stringGranularity, "1000000000000000000")
58+
// }
5659
}

0 commit comments

Comments
 (0)