Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Add error handling
Browse files Browse the repository at this point in the history
Fix #6
  • Loading branch information
alejandro-isaza committed Jun 3, 2018
1 parent 29997e8 commit 5610138
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 116 deletions.
1 change: 1 addition & 0 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use_frameworks!

target 'TrustSDK' do
pod 'TrustCore', inhibit_warnings: true
pod 'Result', '~> 3.0.0'
pod 'SwiftLint'

target 'TrustSDKTests'
Expand Down
10 changes: 7 additions & 3 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
PODS:
- BigInt (3.0.1):
- SipHash (~> 1.2)
- Result (3.0.0)
- SipHash (1.2.0)
- SwiftLint (0.25.1)
- TrezorCrypto (0.0.5)
Expand All @@ -9,24 +10,27 @@ PODS:
- TrezorCrypto

DEPENDENCIES:
- Result (~> 3.0.0)
- SwiftLint
- TrustCore

SPEC REPOS:
https://github.com/cocoapods/specs.git:
https://github.com/CocoaPods/Specs.git:
- BigInt
- Result
- SipHash
- SwiftLint
- TrezorCrypto
- TrustCore

SPEC CHECKSUMS:
BigInt: 8e8a52161c745cd3ab78e3dc346a9fbee51e6cf6
Result: 1b3e431f37cbcd3ad89c6aa9ab0ae55515fae3b6
SipHash: c6e9e43e9c531b5bc6602545130c26194a6d31ce
SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
TrezorCrypto: ecef681446bf02af6248d3b5e394026d7e766e56
TrustCore: 688df9a241008cf9cfa3842ec8ef28777a8b7534

PODFILE CHECKSUM: b6267ac7ce805f5dd81881e942495aaad38e26ba
PODFILE CHECKSUM: 49f6a8bcaf5751c9c12fb27d8c8c9f7da0647622

COCOAPODS: 1.5.2
COCOAPODS: 1.5.0
15 changes: 15 additions & 0 deletions Sources/Error.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright © 2018 Trust.
//
// This file is part of TrustSDK. The full TrustSDK copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import Foundation

public enum WalletError: String, LocalizedError {
/// Error generated when the user cancells the sign request.
case cancelled

/// Error generated when the request is invalid.
case invalidRequest
}
14 changes: 10 additions & 4 deletions Sources/TrustSDK/Commands/SignMessageCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import Result
import TrustCore

public class SignMessageCommand: Command {
Expand All @@ -19,7 +20,7 @@ public class SignMessageCommand: Command {
public var callbackScheme: String

/// Completion closure
public var completion: (Data) -> Void
public var completion: (Result<Data, WalletError>) -> Void

public var callback: URL {
var components = URLComponents()
Expand All @@ -28,7 +29,7 @@ public class SignMessageCommand: Command {
return components.url!
}

public init(message: Data, address: Address? = nil, callbackScheme: String, completion: @escaping (Data) -> Void) {
public init(message: Data, address: Address? = nil, callbackScheme: String, completion: @escaping (Result<Data, WalletError>) -> Void) {
self.message = message
self.address = address
self.callbackScheme = callbackScheme
Expand All @@ -53,19 +54,24 @@ public class SignMessageCommand: Command {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), components.host == name else {
return false
}
if let errorString = components.queryItems?.first(where: { $0.name == "error" })?.value, let error = WalletError(rawValue: errorString) {
completion(.failure(error))
return true
}

guard let result = components.queryItems?.first(where: { $0.name == "result" })?.value else {
return false
}
guard let data = Data(base64Encoded: result) else {
return false
}
completion(data)
completion(.success(data))
return true
}
}

public extension TrustSDK {
public func signMessage(_ message: Data, address: Address? = nil, completion: @escaping (Data) -> Void) {
public func signMessage(_ message: Data, address: Address? = nil, completion: @escaping (Result<Data, WalletError>) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/TrustSDK/Commands/SignPersonalMessageCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// file LICENSE at the root of the source code distribution tree.

import Foundation
import Result
import TrustCore

public final class SignPersonalMessageCommand: SignMessageCommand {
Expand All @@ -17,7 +18,7 @@ public final class SignPersonalMessageCommand: SignMessageCommand {
}

public extension TrustSDK {
public func signPersonalMessage(_ message: Data, address: Address? = nil, completion: @escaping (Data) -> Void) {
public func signPersonalMessage(_ message: Data, address: Address? = nil, completion: @escaping (Result<Data, WalletError>) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
}
Expand Down
15 changes: 11 additions & 4 deletions Sources/TrustSDK/Commands/SignTransactionCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// file LICENSE at the root of the source code distribution tree.

import BigInt
import Result
import TrustCore

public final class SignTransactionCommand: Command {
Expand All @@ -14,7 +15,7 @@ public final class SignTransactionCommand: Command {
public var transaction: Transaction

/// Completion closure
public var completion: (Data) -> Void
public var completion: (Result<Data, WalletError>) -> Void

/// Callback scheme
public var callbackScheme: String
Expand All @@ -26,7 +27,7 @@ public final class SignTransactionCommand: Command {
return components.url!
}

public init(transaction: Transaction, callbackScheme: String, completion: @escaping (Data) -> Void) {
public init(transaction: Transaction, callbackScheme: String, completion: @escaping (Result<Data, WalletError>) -> Void) {
self.transaction = transaction
self.completion = completion
self.callbackScheme = callbackScheme
Expand Down Expand Up @@ -54,19 +55,25 @@ public final class SignTransactionCommand: Command {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), components.host == name else {
return false
}

if let errorString = components.queryItems?.first(where: { $0.name == "error" })?.value, let error = WalletError(rawValue: errorString) {
completion(.failure(error))
return true
}

guard let result = components.queryItems?.first(where: { $0.name == "result" })?.value else {
return false
}
guard let data = Data(base64Encoded: result) else {
return false
}
completion(data)
completion(.success(data))
return true
}
}

public extension TrustSDK {
public func signTransaction(_ transaction: Transaction, completion: @escaping (Data) -> Void) {
public func signTransaction(_ transaction: Transaction, completion: @escaping (Result<Data, WalletError>) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
}
Expand Down
56 changes: 30 additions & 26 deletions Sources/TrustSDK/ObjCWrapper/TrustSDKObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,49 @@
// This file is part of TrustSDK. The full TrustSDK copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.
#if XAMARIN

import Foundation
import TrustCore
import BigInt

@objc(TrustSDK)
public extension TrustSDK {
@objc
public func signMessage(_ message: Data, address: String? = nil, completion: @escaping (Data) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
public func signMessage(_ message: Data, address: String? = nil, success: @escaping (Data) -> Void, failure: @escaping (NSError) -> Void) {
signMessage(message) { result in
switch result {
case .success(let signedMesssage):
success(signedMesssage)
case .failure(let error):
failure(error as NSError)
}
}
let addr = Address(string: address!)
let command = SignMessageCommand(message: message, address: addr, callbackScheme: callbackScheme, completion: completion)
execute(command: command)
}

@objc
public func signTransaction(_ gasPrice: String, _ gasLimit: UInt64, _ address: String, amount: String, completion: @escaping (Data) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
}
let gasP = BigInt(gasPrice)
let addr = Address(string: address)
var transaction = Transaction(gasPrice: gasP!, gasLimit: gasLimit, to: addr!)
let am = BigInt(amount)
transaction.amount = am!
public func signTransaction(_ gasPrice: String, _ gasLimit: UInt64, _ address: String, amount: String, success: @escaping (Data) -> Void, failure: @escaping (NSError) -> Void) {
var transaction = Transaction(gasPrice: BigInt(gasPrice)!, gasLimit: gasLimit, to: Address(string: address)!)
transaction.amount = BigInt(amount)!

let command = SignTransactionCommand(transaction: transaction, callbackScheme: callbackScheme, completion: completion)
execute(command: command)
signTransaction(transaction) { result in
switch result {
case .success(let signedMesssage):
success(signedMesssage)
case .failure(let error):
failure(error as NSError)
}
}
}

@objc
public func signPersonalMessage(_ message: Data, address: String? = nil, completion: @escaping (Data) -> Void) {
guard WalletAppManager.hasWalletApp else {
return fallbackToInstall()
public func signPersonalMessage(_ message: Data, address: String? = nil, success: @escaping (Data) -> Void, failure: @escaping (NSError) -> Void) {
signPersonalMessage(message, address: address.flatMap({ Address(string: $0) })) { result in
switch result {
case .success(let signedMesssage):
success(signedMesssage)
case .failure(let error):
failure(error as NSError)
}
}
let addr = Address(string: address!)
let command = SignPersonalMessageCommand(message: message, address: addr, callbackScheme: callbackScheme, completion: completion)
execute(command: command)
}
}

#endif
51 changes: 27 additions & 24 deletions Sources/TrustWalletSDK/TrustWalletSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// file LICENSE at the root of the source code distribution tree.

import BigInt
import Result
import TrustCore
import UIKit

Expand Down Expand Up @@ -46,24 +47,24 @@ public final class TrustWalletSDK {
}
let address = components.queryParameterValue(for: "address").flatMap({ Address(eip55: $0) })
let callback = components.queryParameterValue(for: "callback").flatMap({ URL(string: $0) })
delegate.signMessage(message, address: address) { signedMessage in
delegate.signMessage(message, address: address) { result in
if let callback = callback {
self.handleSignMessageResult(signedMessage, callback: callback)
self.handleSignMessageResult(result, callback: callback)
}
}

return true
}

private func handleSignMessageResult(_ signedMessage: Data?, callback: URL) {
guard let signedMessage = signedMessage else {
callbackWithFailure(url: callback)
return
}

if var callbackComponents = URLComponents(url: callback, resolvingAgainstBaseURL: false) {
callbackComponents.append(queryItem: URLQueryItem(name: "result", value: signedMessage.base64EncodedString()))
UIApplication.shared.open(callbackComponents.url!, options: [:], completionHandler: nil)
private func handleSignMessageResult(_ result: Result<Data, WalletError>, callback: URL) {
switch result {
case .success(let signedMessage):
if var callbackComponents = URLComponents(url: callback, resolvingAgainstBaseURL: false) {
callbackComponents.append(queryItem: URLQueryItem(name: "result", value: signedMessage.base64EncodedString()))
UIApplication.shared.open(callbackComponents.url!, options: [:], completionHandler: nil)
}
case .failure(let error):
callbackWithFailure(url: callback, error: error)
}
}

Expand Down Expand Up @@ -96,28 +97,30 @@ public final class TrustWalletSDK {

transaction.nonce = components.queryParameterValue(for: "nonce").flatMap({ UInt64($0) }) ?? 0

delegate.signTransaction(transaction) { signedTransaction in
delegate.signTransaction(transaction) { result in
if let callback = callback {
self.handleSignTransactionResult(signedTransaction, callback: callback)
self.handleSignTransactionResult(result, callback: callback)
}
}

return true
}

private func handleSignTransactionResult(_ signedTransaction: Data?, callback: URL) {
guard let signedTransaction = signedTransaction else {
callbackWithFailure(url: callback)
return
}

if var callbackComponents = URLComponents(url: callback, resolvingAgainstBaseURL: false) {
callbackComponents.append(queryItem: URLQueryItem(name: "result", value: signedTransaction.base64EncodedString()))
UIApplication.shared.open(callbackComponents.url!, options: [:], completionHandler: nil)
private func handleSignTransactionResult(_ result: Result<Data, WalletError>, callback: URL) {
switch result {
case .success(let signedTransaction):
if var callbackComponents = URLComponents(url: callback, resolvingAgainstBaseURL: false) {
callbackComponents.append(queryItem: URLQueryItem(name: "result", value: signedTransaction.base64EncodedString()))
UIApplication.shared.open(callbackComponents.url!, options: [:], completionHandler: nil)
}
case .failure(let error):
callbackWithFailure(url: callback, error: error)
}
}

private func callbackWithFailure(url: URL) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
private func callbackWithFailure(url: URL, error: WalletError) {
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
components.queryItems = [URLQueryItem(name: "error", value: error.rawValue)]
UIApplication.shared.open(components.url!, options: [:], completionHandler: nil)
}
}
7 changes: 4 additions & 3 deletions Sources/TrustWalletSDK/WalletDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import Result
import TrustCore

/// Wallets should implement this delegate to handle requests
Expand All @@ -14,20 +15,20 @@ public protocol WalletDelegate: class {
/// - message: message data to sign
/// - address: address to use for signing
/// - completion: completing closure to call with the signed message or `nil` on failure
func signMessage(_ message: Data, address: Address?, completion: @escaping (Data?) -> Void)
func signMessage(_ message: Data, address: Address?, completion: @escaping (Result<Data, WalletError>) -> Void)

/// Signs a personal message with the specified address
///
/// - Parameters:
/// - message: message data to sign
/// - address: address to use for signing
/// - completion: completing closure to call with the signed message or `nil` on failure
func signPersonalMessage(_ message: Data, address: Address?, completion: @escaping (Data?) -> Void)
func signPersonalMessage(_ message: Data, address: Address?, completion: @escaping (Result<Data, WalletError>) -> Void)

/// Signs a transaction
///
/// - Parameters:
/// - transaction: transaction to sign
/// - completion: completing closure to call with the signed message or `nil` on failure
func signTransaction(_ transaction: Transaction, completion: @escaping (Data?) -> Void)
func signTransaction(_ transaction: Transaction, completion: @escaping (Result<Data, WalletError>) -> Void)
}
6 changes: 5 additions & 1 deletion Tests/TrustSDK/SignMessageCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ class SignMessageCommandTests: XCTestCase {
func testHandleCallback() {
let message = Data(hexString: "1234")!
let commandCompletedExpectation = expectation(description: "Command completed")
let command = SignMessageCommand(message: message, address: nil, callbackScheme: "app") { data in
let command = SignMessageCommand(message: message, address: nil, callbackScheme: "app") { result in
commandCompletedExpectation.fulfill()
guard case .success(let data) = result else {
XCTFail("Expected success")
return
}
XCTAssertEqual(data, message)
}

Expand Down
Loading

0 comments on commit 5610138

Please sign in to comment.