Skip to content

Commit

Permalink
throws error when failed to convert wei -> ether or ether -> wei, rem…
Browse files Browse the repository at this point in the history
…ove force-unwrapping
  • Loading branch information
yuzushioh committed Jun 16, 2018
1 parent 7940223 commit 2a6dc73
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 64 deletions.
26 changes: 15 additions & 11 deletions EthereumKit/Helper/Converter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@
public typealias Ether = Decimal
public typealias Wei = BInt

extension Wei {
public init?(hex: String) {
self.init(hex, radix: 16)
}
}

public final class Converter {
private static let etherInWei = Decimal(1000000000000000000)

public static func toEther(wei: Wei) -> Ether {
guard let decimalWei = Decimal(string: wei.description)else {
fatalError("Failed to convert Wei to Ether")
/// Convert Wei(BInt) unit to Ether(Decimal) unit
public static func toEther(wei: Wei) throws -> Ether {
guard let decimalWei = Decimal(string: wei.description) else {
throw EthereumKitError.convertError(.failedToConvert(wei.description))
}
return decimalWei / etherInWei
}

public static func toWei(ether: Ether) -> Wei {
/// Convert Ether(Decimal) unit to Wei(BInt) unit
public static func toWei(ether: Ether) throws -> Wei {
guard let wei = Wei((ether * etherInWei).description) else {
fatalError("Faied to convert Ether to Wei")
throw EthereumKitError.convertError(.failedToConvert(ether * etherInWei))
}
return wei
}

/// Convert Ether(String) unit to Wei(BInt) unit
public static func toWei(ether: String) throws -> Wei {
guard let decimalEther = Decimal(string: ether) else {
throw EthereumKitError.convertError(.failedToConvert(ether))
}
return try toWei(ether: decimalEther)
}

// Only used for calcurating gas price and gas limit.
public static func toWei(GWei: Int) -> Int {
return GWei * 1000000000
Expand Down
5 changes: 5 additions & 0 deletions EthereumKit/Helper/EthereumKitError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ public enum EthereumKitError: Error {
case invalidDecimalValue(Any)
}

public enum ConvertError: Error {
case failedToConvert(Any)
}

case requestError(RequestError)
case responseError(ResponseError)
case cryptoError(CryptoError)
case contractError(ContractError)
case convertError(ConvertError)
}
4 changes: 2 additions & 2 deletions EthereumKit/Model/Balance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ public struct Balance {
public let wei: Wei

/// User's balance in ether unit
public var ether: Ether {
return Converter.toEther(wei: wei)
func ether() throws -> Ether {
return try Converter.toEther(wei: wei)
}
}

Expand Down
8 changes: 2 additions & 6 deletions EthereumKit/Model/RawTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public struct RawTransaction {
}

extension RawTransaction {
public init(value: Wei, to: Address, gasPrice: Int, gasLimit: Int, nonce: Int) {
public init(value: Wei, to: String, gasPrice: Int, gasLimit: Int, nonce: Int) {
self.value = value
self.to = to
self.to = Address(string: to)
self.gasPrice = gasPrice
self.gasLimit = gasLimit
self.nonce = nonce
Expand All @@ -41,10 +41,6 @@ extension RawTransaction {
self.nonce = nonce
self.data = data
}

public init(ether: String, to: String, gasPrice: Int, gasLimit: Int, nonce: Int, data: Data = Data()) {
self.init(wei: Converter.toWei(ether: Ether(string: ether)!).description, to: to, gasPrice: gasPrice, gasLimit: gasLimit, nonce: nonce, data: data)
}
}

extension RawTransaction: Codable {
Expand Down
6 changes: 3 additions & 3 deletions EthereumKit/Networking/Request/JSONRPC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public final class JSONRPC {
}

public func response(from resultObject: Any) throws -> Wei {
guard let response = resultObject as? String, let wei = Wei(hex: response.lowercased().stripHexPrefix()) else {
guard let response = resultObject as? String, let wei = Wei(response.lowercased().stripHexPrefix(), radix: 16) else {
throw JSONRPCError.unexpectedTypeObject(resultObject)
}
return wei
Expand All @@ -29,7 +29,7 @@ public final class JSONRPC {
}

public func response(from resultObject: Any) throws -> Balance {
guard let response = resultObject as? String, let wei = Wei(hex: response.lowercased().stripHexPrefix()) else {
guard let response = resultObject as? String, let wei = Wei(response.lowercased().stripHexPrefix(), radix: 16) else {
throw JSONRPCError.unexpectedTypeObject(resultObject)
}
return Balance(wei: wei)
Expand Down Expand Up @@ -173,7 +173,7 @@ public final class JSONRPC {
}

public func response(from resultObject: Any) throws -> Wei {
guard let response = resultObject as? String, let wei = Wei(hex: response.lowercased().stripHexPrefix()) else {
guard let response = resultObject as? String, let wei = Wei(response.lowercased().stripHexPrefix(), radix: 16) else {
throw JSONRPCError.unexpectedTypeObject(resultObject)
}
return wei
Expand Down
32 changes: 16 additions & 16 deletions EthereumKitTests/ConverterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import XCTest
class ConverterTests: XCTestCase {

func testConverter() {
XCTAssertEqual(Converter.toEther(wei: Wei("100000000000000")!), 0.0001)
XCTAssertEqual(Converter.toEther(wei: Wei("1000000000000000")!), 0.001)
XCTAssertEqual(Converter.toEther(wei: Wei("10000000000000000")!), 0.01)
XCTAssertEqual(Converter.toEther(wei: Wei("100000000000000000")!), 0.1)
XCTAssertEqual(Converter.toEther(wei: Wei("1000000000000000000")!), 1)
XCTAssertEqual(Converter.toEther(wei: Wei("10000000000000000000")!), 10)
XCTAssertEqual(Converter.toEther(wei: Wei("100000000000000000000")!), 100)
XCTAssertEqual(Converter.toEther(wei: Wei("1000000000000000000000")!), 1000)
XCTAssertEqual(try! Converter.toEther(wei: Wei("100000000000000")!), 0.0001)
XCTAssertEqual(try! Converter.toEther(wei: Wei("1000000000000000")!), 0.001)
XCTAssertEqual(try! Converter.toEther(wei: Wei("10000000000000000")!), 0.01)
XCTAssertEqual(try! Converter.toEther(wei: Wei("100000000000000000")!), 0.1)
XCTAssertEqual(try! Converter.toEther(wei: Wei("1000000000000000000")!), 1)
XCTAssertEqual(try! Converter.toEther(wei: Wei("10000000000000000000")!), 10)
XCTAssertEqual(try! Converter.toEther(wei: Wei("100000000000000000000")!), 100)
XCTAssertEqual(try! Converter.toEther(wei: Wei("1000000000000000000000")!), 1000)

XCTAssertEqual(Converter.toWei(ether: Ether(string: "0.0001")!).description, "100000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "0.001")!).description, "1000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "0.01")!).description, "10000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "0.1")!).description, "100000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "1")!).description, "1000000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "10")!).description, "10000000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "100")!).description, "100000000000000000000")
XCTAssertEqual(Converter.toWei(ether: Ether(string: "1000")!).description, "1000000000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "0.0001")!).description, "100000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "0.001")!).description, "1000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "0.01")!).description, "10000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "0.1")!).description, "100000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "1")!).description, "1000000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "10")!).description, "10000000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "100")!).description, "100000000000000000000")
XCTAssertEqual(try! Converter.toWei(ether: Ether(string: "1000")!).description, "1000000000000000000000")

XCTAssertEqual(Converter.toWei(GWei: 1), 1000000000)
XCTAssertEqual(Converter.toWei(GWei: 10), 10000000000)
Expand Down
12 changes: 6 additions & 6 deletions EthereumKitTests/EIP155SignerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction1 = RawTransaction(
value: Wei("10000000000000000")!,
to: Address(string: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F"),
to: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 2
Expand All @@ -20,7 +20,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction2 = RawTransaction(
value: Wei("10000000000000000")!,
to: Address(string: "0x88b44BC83add758A3642130619D61682282850Df"),
to: "0x88b44BC83add758A3642130619D61682282850Df",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 4
Expand All @@ -33,7 +33,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction3 = RawTransaction(
value: Wei("10000000000000000")!,
to: Address(string: "0x72AAb5461F9bE958E1c375285CC2aA7De89D02A1"),
to: "0x72AAb5461F9bE958E1c375285CC2aA7De89D02A1",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 25
Expand All @@ -50,7 +50,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction1 = RawTransaction(
value: Wei("10000000000000000")!,
to: Address(string: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F"),
to: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 2
Expand All @@ -63,7 +63,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction2 = RawTransaction(
value: Wei("10000000000000000")!,
to: Address(string: "0x88b44BC83add758A3642130619D61682282850Df"),
to: "0x88b44BC83add758A3642130619D61682282850Df",
gasPrice: 99000000000,
gasLimit: 200000,
nonce: 4
Expand All @@ -76,7 +76,7 @@ class EIP155SignerTests: XCTestCase {

let rawTransaction3 = RawTransaction(
value: Wei("20000000000000000")!,
to: Address(string: "0x72AAb5461F9bE958E1c375285CC2aA7De89D02A1"),
to: "0x72AAb5461F9bE958E1c375285CC2aA7De89D02A1",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 25
Expand Down
8 changes: 4 additions & 4 deletions EthereumKitTests/EthereumKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ class EthereumKitTests: XCTestCase {
}

func testBalance() {
let firstBalanceHex = "0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000" // 1ether = 1000000000000000000wei
let firstBalanceHex = "0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000" // 1ether = 1000000000000000000 wei
let firstBalanceWei = Wei(str: firstBalanceHex.lowercased().stripHexPrefix(), radix: 16)!
let firstBalance = Balance(wei: firstBalanceWei)
XCTAssertEqual(firstBalance.wei, Wei(number: "1000000000000000000", withBase: 10))
XCTAssertEqual(firstBalance.ether, Ether(1))
let secondBalanceHex = "0x0000000000000000000000000000000000000000000000056BC75E2D63100000" // 100ether = 100000000000000000000wei
XCTAssertEqual(try! firstBalance.ether(), Ether(1))
let secondBalanceHex = "0x0000000000000000000000000000000000000000000000056BC75E2D63100000" // 100ether = 100000000000000000000 wei
let secondBalanceWei = Wei(str: secondBalanceHex.lowercased().stripHexPrefix(), radix: 16)!
let secondBalance = Balance(wei: secondBalanceWei)
XCTAssertEqual(secondBalance.wei, Wei(number: "100000000000000000000", withBase: 10))
XCTAssertEqual(secondBalance.ether, Ether(100))
XCTAssertEqual(try! secondBalance.ether(), Ether(100))
}
}
14 changes: 7 additions & 7 deletions EthereumKitTests/TransactionSigningTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning() {
let rawTransaction = RawTransaction(
value: Wei("1000000000000000000")!,
to: Address(string: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F"),
to: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 5
Expand Down Expand Up @@ -39,7 +39,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning2() {
let rawTransaction = RawTransaction(
value: Wei("100000000000000000")!,
to: Address(string: "0x3B958949EfCc8362Dd05179cCE8eB5e16BefeBdA"),
to: "0x3B958949EfCc8362Dd05179cCE8eB5e16BefeBdA",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 5
Expand Down Expand Up @@ -71,7 +71,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning3() {
let rawTransaction = RawTransaction(
value: Wei("500000000000000000")!,
to: Address(string: "0xfc9d3987f7fcd9181393084a94814385b28cEf81"),
to: "0xfc9d3987f7fcd9181393084a94814385b28cEf81",
gasPrice: 99000000000,
gasLimit: 200000,
nonce: 5
Expand Down Expand Up @@ -103,7 +103,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning4() {
let rawTransaction = RawTransaction(
value: Wei("1000000000000000000")!,
to: Address(string: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F"),
to: "0x91c79f31De5208fadCbF83f0a7B0A9b6d8aBA90F",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 0
Expand Down Expand Up @@ -135,7 +135,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning5() {
let rawTransaction = RawTransaction(
value: Wei("1000000000000000000")!,
to: Address(string: "0x3B958949EfCc8362Dd05179cCE8eB5e16BefeBdA"),
to: "0x3B958949EfCc8362Dd05179cCE8eB5e16BefeBdA",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 0
Expand Down Expand Up @@ -167,7 +167,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning6() {
let rawTransaction = RawTransaction(
value: Wei("5000000000000000000")!,
to: Address(string: "0xfc9d3987f7fcd9181393084a94814385b28cEf81"),
to: "0xfc9d3987f7fcd9181393084a94814385b28cEf81",
gasPrice: 99000000000,
gasLimit: 200000,
nonce: 0
Expand Down Expand Up @@ -199,7 +199,7 @@ class TransactionSigningTests: XCTestCase {
func testTransactionSigning7() {
let rawTransaction = RawTransaction(
value: Wei("1000000000000000")!,
to: Address(string: "0x88b44BC83add758A3642130619D61682282850Df"),
to: "0x88b44BC83add758A3642130619D61682282850Df",
gasPrice: 99000000000,
gasLimit: 21000,
nonce: 0
Expand Down
9 changes: 8 additions & 1 deletion Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ class ViewController: UIViewController {
geth.getTransactionCount(of: address) { result in
switch result {
case .success(let nonce):
let rawTransaction = RawTransaction(ether: "0.0001", to: address, gasPrice: Converter.toWei(GWei: 10), gasLimit: 21000, nonce: nonce)
let wei: BInt
do {
wei = try Converter.toWei(ether: "0.00001")
} catch let error {
fatalError("Error: \(error.localizedDescription)")
}

let rawTransaction = RawTransaction(value: wei, to: address, gasPrice: Converter.toWei(GWei: 10), gasLimit: 21000, nonce: nonce)
let tx: String
do {
tx = try wallet.sign(rawTransaction: rawTransaction)
Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ let seed = Mnemonic.createSeed(mnemonic: mnemonic)

// BIP32: Key derivation and address generation

let wallet: Wallet
do {
wallet = try Wallet(seed: seed, network: .main)
} catch let error {
fatalError("Error: \(error.localizedDescription)")
}
let wallet = try! Wallet(seed: seed, network: .main)

// Send some ether
let rawTransaction = RawTransaction(ether: "0.15", to: address, gasPrice: Converter.toWei(GWei: 10), gasLimit: 21000, nonce: 0)
let tx = try wallet.signTransaction(rawTransaction)

let rawTransaction = RawTransaction(
ether: try! Converter.toWei(ether: "0.00001"),
to: address,
gasPrice: Converter.toWei(GWei: 10),
gasLimit: 21000,
nonce: 0
)

let tx = try! wallet.signTransaction(rawTransaction)
geth.sendRawTransaction(rawTransaction: tx) { result in
// Do something...
}
Expand Down

0 comments on commit 2a6dc73

Please sign in to comment.