Skip to content

Commit 46adcea

Browse files
committed
added EtherscanTransactionChecker
1 parent 3394b0f commit 46adcea

File tree

3 files changed

+127
-1
lines changed

3 files changed

+127
-1
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// EtherscanTransactionChecker.swift
3+
// Created by albertopeam on 28/12/22.
4+
//
5+
6+
import Foundation
7+
import _Concurrency
8+
9+
public struct EtherscanTransactionChecker: TransactionChecker {
10+
private let urlSession: URLSessionProxy
11+
private let apiKey: String
12+
13+
public init(urlSession: URLSessionProxy, apiKey: String) {
14+
self.urlSession = urlSession
15+
self.apiKey = apiKey
16+
}
17+
18+
public func hasTransactions(address: String) async throws -> Bool {
19+
let urlString = "https://api.etherscan.io/api?module=account&action=txlist&address=\(address)&startblock=0&page=1&offset=1&sort=asc&apikey=\(apiKey)"
20+
guard let url = URL(string: urlString) else {
21+
throw EtherscanTransactionCheckerError.invalidUrl
22+
}
23+
let request = URLRequest(url: url)
24+
let result = try await urlSession.data(request: request)
25+
let response = try JSONDecoder().decode(Response.self, from: result.0)
26+
return !response.result.isEmpty
27+
}
28+
}
29+
30+
extension EtherscanTransactionChecker {
31+
struct Response: Codable {
32+
let result: [Transaction]
33+
}
34+
struct Transaction: Codable {}
35+
}
36+
37+
public enum EtherscanTransactionCheckerError: Error {
38+
case invalidUrl
39+
}
40+
41+
public protocol URLSessionProxy {
42+
func data(request: URLRequest) async throws -> (Data, HTTPURLResponse)
43+
}
44+
45+
extension URLSession: URLSessionProxy {
46+
public func data(request: URLRequest) async throws -> (Data, HTTPURLResponse) {
47+
return try await data(for: request)
48+
}
49+
}

Tests/web3swiftTests/localTests/BIP44Tests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import XCTest
77
import Web3Core
88
@testable import web3swift
99

10-
final class BIP44Tests: LocalTestCase {
10+
final class BIP44Tests: XCTestCase {
1111
private var accountZeroScannedAddresses: [String]!
1212
private var accountZeroAndOneScannedAddresses: [String]!
1313
private var mockTransactionChecker: MockTransactionChecker!
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// EtherscanTransactionCheckerTests.swift
3+
// Created by albertopeam on 28/12/22.
4+
//
5+
6+
import XCTest
7+
@testable import Web3Core
8+
9+
final class EtherscanTransactionCheckerTests: XCTestCase {
10+
private var testApiKey: String!
11+
private var vitaliksAddress: String!
12+
private var emptyAddress: String!
13+
14+
override func setUpWithError() throws {
15+
try super.setUpWithError()
16+
testApiKey = "4HVPVMV1PN6NGZDFXZIYKEZRP53IA41KVC"
17+
vitaliksAddress = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
18+
emptyAddress = "0x1BeY3KhtHpfATH5Yqxz9d8Z1XbqZFSXtK7"
19+
}
20+
21+
override func tearDownWithError() throws {
22+
try super.tearDownWithError()
23+
testApiKey = nil
24+
vitaliksAddress = nil
25+
emptyAddress = nil
26+
}
27+
28+
func testHasTransactions() async throws {
29+
let sut = EtherscanTransactionChecker(urlSession: URLSession.shared, apiKey: testApiKey)
30+
31+
let result = try await sut.hasTransactions(address: vitaliksAddress)
32+
33+
XCTAssertTrue(result)
34+
}
35+
36+
func testHasNotTransactions() async throws {
37+
let sut = EtherscanTransactionChecker(urlSession: URLSession.shared, apiKey: testApiKey)
38+
39+
let result = try await sut.hasTransactions(address: emptyAddress)
40+
41+
XCTAssertFalse(result)
42+
}
43+
44+
func testNetworkError() async throws {
45+
do {
46+
let urlSessionMock = URLSessionMock()
47+
urlSessionMock.response = (Data(), try XCTUnwrap(HTTPURLResponse(url: try XCTUnwrap(URL(string: "https://")), statusCode: 500, httpVersion: nil, headerFields: nil)))
48+
let sut = EtherscanTransactionChecker(urlSession: urlSessionMock, apiKey: testApiKey)
49+
50+
_ = try await sut.hasTransactions(address: vitaliksAddress)
51+
52+
XCTFail()
53+
} catch {
54+
XCTAssertTrue(true)
55+
}
56+
}
57+
58+
func testWrongApiKey() async throws {
59+
do {
60+
let sut = EtherscanTransactionChecker(urlSession: URLSession.shared, apiKey: "")
61+
62+
_ = try await sut.hasTransactions(address: "")
63+
64+
XCTFail()
65+
} catch DecodingError.typeMismatch {
66+
XCTAssertTrue(true)
67+
}
68+
}
69+
}
70+
71+
final class URLSessionMock: URLSessionProxy {
72+
var response: (Data, HTTPURLResponse) = (Data(), HTTPURLResponse())
73+
74+
func data(request: URLRequest) async throws -> (Data, HTTPURLResponse) {
75+
return response
76+
}
77+
}

0 commit comments

Comments
 (0)