-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature/ethereum-service #4
base: master
Are you sure you want to change the base?
Changes from 14 commits
a3ff0c0
8a1a04c
94c70d8
aa7b2f7
531f96a
d2c77c7
4a67b61
f6759d7
60cc8d4
cd08716
01f35f0
18e9781
9610444
96d7335
664006c
e9aa0c9
4acd5b8
192a91e
2701f54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import Foundation | ||
|
||
extension Data { | ||
/// A hexadecimal string representation of the bytes. | ||
func hexEncodedString() -> String { | ||
let hexDigits = Array("0123456789abcdef".utf16) | ||
var hexChars = [UTF16.CodeUnit]() | ||
hexChars.reserveCapacity(count * 2) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
for byte in self { | ||
let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16) | ||
hexChars.append(hexDigits[index1]) | ||
hexChars.append(hexDigits[index2]) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
return String(utf16CodeUnits: hexChars, count: hexChars.count) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Foundation | ||
|
||
extension String { | ||
/// A data representation of the hexadecimal bytes in this string. | ||
func hexDecodedData() -> Data { | ||
// Get the UTF8 characters of this string | ||
let chars = Array(utf8) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
// Keep the bytes in an UInt8 array and later convert it to Data | ||
var bytes = [UInt8]() | ||
bytes.reserveCapacity(count / 2) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
// It is a lot faster to use a lookup map instead of strtoul | ||
let map: [UInt8] = [ | ||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567 | ||
0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>? | ||
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // HIJKLMNO | ||
] | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
// Grab two characters at a time, map them and turn it into a byte | ||
for i in stride(from: 0, to: count, by: 2) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Variable name should be between 3 and 40 characters long: 'i' |
||
let index1 = Int(chars[i] & 0x1F ^ 0x10) | ||
let index2 = Int(chars[i + 1] & 0x1F ^ 0x10) | ||
bytes.append(map[index1] << 4 | map[index2]) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines should not have trailing whitespace. |
||
return Data(bytes) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import Foundation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
import UB | ||
|
||
public class EthereumService: Service { | ||
let url: URL | ||
|
||
/// Initializes an Ethereum Service with a RPC HTTP url | ||
ec2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public init(url: URL) { | ||
self.url = url | ||
} | ||
|
||
// handle gets called when an Ethereum service is called. | ||
ec2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public func handle(message: Message, node: Node) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function body should span 40 lines or less excluding comments and whitespace: currently spans 53 lines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function body should span 40 lines or less excluding comments and whitespace: currently spans 48 lines |
||
// The first btye of the message is the JSONRPC method | ||
let methodID = message.message[0] | ||
|
||
switch methodID { | ||
case 0: | ||
let address = "0x" + message.message[1 ..< message.message.count].hexEncodedString() | ||
getBalance(address: address) { result in | ||
switch result { | ||
case let .success(balance): | ||
let messageResponse = Message( | ||
proto: UBID(repeating: 1, count: 1), | ||
recipient: message.origin, | ||
from: message.recipient, | ||
origin: message.recipient, | ||
message: balance | ||
) | ||
node.send(messageResponse) | ||
case let .failure(error): | ||
print(error) | ||
} | ||
} | ||
case 1: | ||
let address = "0x" + message.message[1 ..< message.message.count].hexEncodedString() | ||
getTransactionCount(address: address) { result in | ||
switch result { | ||
case let .success(nonce): | ||
let messageResponse = Message( | ||
proto: UBID(repeating: 1, count: 1), | ||
recipient: message.origin, | ||
from: message.recipient, | ||
origin: message.recipient, | ||
message: nonce | ||
) | ||
node.send(messageResponse) | ||
case let .failure(error): | ||
print(error) | ||
} | ||
} | ||
case 2: | ||
let signedTransaction = "0x" + message.message[1 ..< message.message.count].hexEncodedString() | ||
sendRawTransaction(signedTransaction: signedTransaction) { result in | ||
switch result { | ||
case let .success(balance): | ||
let messageResponse = Message( | ||
proto: UBID(repeating: 1, count: 1), | ||
recipient: message.origin, | ||
from: message.recipient, | ||
origin: message.recipient, | ||
message: balance | ||
) | ||
node.send(messageResponse) | ||
case let .failure(error): | ||
print(error) | ||
} | ||
} | ||
return | ||
default: | ||
print("default") | ||
return | ||
} | ||
} | ||
|
||
internal func httpRequest(request: URLRequest, completion: @escaping (Result<Data, Error>) -> Void) { | ||
_ = URLSession.shared.dataTask(with: request) { data, _, error in | ||
guard let data = data, error == nil else { | ||
print(error?.localizedDescription ?? "No data") | ||
completion(.failure(error!)) | ||
return | ||
} | ||
completion(.success(data)) | ||
}.resume() | ||
} | ||
|
||
internal func getBalance(address: String, completion: @escaping (Result<Data, Error>) -> Void) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
var request = URLRequest(url: url) | ||
request.httpMethod = "POST" | ||
let payload: [String: Any] = [ | ||
ec2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"jsonrpc": "2.0", | ||
"method": "eth_getBalance", | ||
"params": [address, "latest"], | ||
"id": 1 | ||
] | ||
let jsonPayload = try! JSONSerialization.data(withJSONObject: payload) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Force tries should be avoided.
ec2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
request.httpBody = jsonPayload | ||
|
||
httpRequest(request: request) { result in | ||
switch result { | ||
case let .success(balance): | ||
completion(.success(balance)) | ||
case let .failure(error): | ||
completion(.failure(error)) | ||
} | ||
} | ||
} | ||
|
||
internal func getTransactionCount(address: String, completion: @escaping (Result<Data, Error>) -> Void) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar blocks of code found in 2 locations. Consider refactoring. |
||
var request = URLRequest(url: url) | ||
request.httpMethod = "POST" | ||
let payload: [String: Any] = [ | ||
"jsonrpc": "2.0", | ||
"method": "eth_getTransactionCount", | ||
"params": [address, "latest"], | ||
"id": 1 | ||
] | ||
let jsonPayload = try! JSONSerialization.data(withJSONObject: payload) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Force tries should be avoided. |
||
request.httpBody = jsonPayload | ||
|
||
httpRequest(request: request) { result in | ||
switch result { | ||
case let .success(nonce): | ||
completion(.success(nonce)) | ||
case let .failure(error): | ||
completion(.failure(error)) | ||
} | ||
} | ||
} | ||
|
||
internal func sendRawTransaction(signedTransaction: String, completion: @escaping (Result<Data, Error>) -> Void) { | ||
var request = URLRequest(url: url) | ||
request.httpMethod = "POST" | ||
let payload: [String: Any] = [ | ||
"jsonrpc": "2.0", | ||
"method": "eth_sendRawTransaction", | ||
"params": [signedTransaction], | ||
"id": 1 | ||
] | ||
let jsonPayload = try! JSONSerialization.data(withJSONObject: payload) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Force tries should be avoided. |
||
request.httpBody = jsonPayload | ||
|
||
httpRequest(request: request) { result in | ||
switch result { | ||
case let .success(txHash): | ||
completion(.success(txHash)) | ||
case let .failure(error): | ||
completion(.failure(error)) | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
import XCTest | ||
|
||
|
||
var tests = [XCTestCaseEntry]() | ||
|
||
XCTMain(tests) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
@testable import RelayerFramework | ||
import XCTest | ||
|
||
final class RelayerFrameworkTests: XCTestCase { | ||
func testGetBalance() { | ||
let didFinish = self.expectation(description: #function) | ||
let url: URL = URL(string: "https://rinkeby.infura.io/f7a08ae0242843f1b1cf480454a6bba5")! | ||
let ethService = EthereumService(url: url) | ||
var bal = "" | ||
ethService.getBalance(address: "0x0F64928EcA02147075c7614A7d67B0C3Cb37D5DA") { result in | ||
switch result { | ||
case let .success(balance): | ||
bal = String(data: balance, encoding: .utf8)! | ||
didFinish.fulfill() | ||
case let .failure(error): | ||
print(error) | ||
} | ||
} | ||
|
||
wait(for: [didFinish], timeout: 5) | ||
XCTAssertEqual(bal, "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x1a55734bf06dc800\"}") | ||
} | ||
|
||
static var allTests = [ | ||
("testGetBalance", testGetBalance), | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// | ||
// Transport.swift | ||
// Relayer | ||
// | ||
// Created by Eric Tu on 9/25/19. | ||
// | ||
|
||
import Foundation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Limit vertical whitespace to a single empty line. Currently 2.