merged with upstream

pull/4/head
James Sangalli 7 years ago
commit 39a1e6649d
  1. 125
      .idea/workspace.xml
  2. 51
      Trust/Browser/Coordinators/BrowserCoordinator.swift
  3. 9
      Trust/Browser/Types/DappAction.swift
  4. 3
      Trust/Browser/Types/DappCommand.swift
  5. 8
      Trust/Browser/ViewControllers/BrowserViewController.swift
  6. 27
      Trust/EtherClient/EtherKeystore.swift
  7. 3
      Trust/EtherClient/KeyStoreError.swift
  8. 4
      Trust/EtherClient/Keystore.swift
  9. 35
      Trust/Transfer/Coordinators/SignMessageCoordinator.swift
  10. 34
      TrustTests/EtherClient/EtherKeystoreTests.swift
  11. 4
      TrustTests/Factories/FakeKeystore.swift

@ -2,67 +2,16 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="36bad8c5-1e9e-4730-ba80-fb45b953be97" name="Default" comment="">
<change beforePath="" afterPath="$PROJECT_DIR$/JS/.babelrc" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/dist/trust-min.js" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/dist/trust.js" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/gulpfile.babel.js" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/package-lock.json" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/package.json" />
<change beforePath="" afterPath="$PROJECT_DIR$/JS/src/index.js" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Assets.xcassets/settings_preferences.imageset/Contents.json" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Assets.xcassets/settings_preferences.imageset/settings_preferences.png" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Extensions/UINavigationController.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Extensions/UITextFieldAdditions.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Foundation/DecimalFormatter.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Foundation/StringFormatter.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Settings/Controllers/PreferencesController.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Settings/Types/PreferenceOption.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Settings/ViewControllers/PreferencesViewController.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/Trust/Settings/ViewModels/PreferencesViewModel.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/TrustTests/Core/ViewModels/InCoordinatorViewModelTests.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/TrustTests/Factories/PreferencesController.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/TrustTests/Foundation/DecimalNumberFormatterTest.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/TrustTests/Foundation/StringFormatterTest.swift" />
<change beforePath="" afterPath="$PROJECT_DIR$/TrustTests/Settings/Controllers/PreferencesControllerTests.swift" />
<change beforePath="$PROJECT_DIR$/.gitignore" afterPath="$PROJECT_DIR$/.gitignore" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
<change beforePath="$PROJECT_DIR$/Trust.xcodeproj/project.pbxproj" afterPath="$PROJECT_DIR$/Trust.xcodeproj/project.pbxproj" />
<change beforePath="$PROJECT_DIR$/Trust/Accounts/ViewModels/AccountViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Accounts/ViewModels/AccountViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Accounts/ViewModels/AccountsViewController.swift" afterPath="$PROJECT_DIR$/Trust/Accounts/ViewModels/AccountsViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Accounts/Views/AccountViewCell.swift" afterPath="$PROJECT_DIR$/Trust/Accounts/Views/AccountViewCell.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Accounts/Views/AccountViewCell.xib" afterPath="$PROJECT_DIR$/Trust/Accounts/Views/AccountViewCell.xib" />
<change beforePath="$PROJECT_DIR$/Trust/Assets.xcassets/glasses.imageset/glasses@3x.png" afterPath="$PROJECT_DIR$/Trust/Assets.xcassets/glasses.imageset/glasses@3x.png" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/Factory/WKWebViewConfiguration.swift" afterPath="$PROJECT_DIR$/Trust/Browser/Factory/WKWebViewConfiguration.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/Types/BrowserURLParser.swift" afterPath="$PROJECT_DIR$/Trust/Browser/Types/BrowserURLParser.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Core/ViewModels/InCoordinatorViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Core/ViewModels/InCoordinatorViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/EtherClient/Requests/MarketOrders.swift" afterPath="$PROJECT_DIR$/Trust/EtherClient/Requests/MarketOrders.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Extensions/Address.swift" afterPath="$PROJECT_DIR$/Trust/Extensions/Address.swift" />
<change beforePath="$PROJECT_DIR$/Trust/InCoordinator.swift" afterPath="$PROJECT_DIR$/Trust/InCoordinator.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Info.plist" afterPath="$PROJECT_DIR$/Trust/Info.plist" />
<change beforePath="$PROJECT_DIR$/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Market/SignOrders.swift" afterPath="$PROJECT_DIR$/Trust/Market/SignOrders.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Settings/Types/Config.swift" afterPath="$PROJECT_DIR$/Trust/Settings/Types/Config.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Settings/Types/ConfigExplorer.swift" afterPath="$PROJECT_DIR$/Trust/Settings/Types/ConfigExplorer.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Settings/Types/RPCServers.swift" afterPath="$PROJECT_DIR$/Trust/Settings/Types/RPCServers.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Settings/ViewControllers/SettingsViewController.swift" afterPath="$PROJECT_DIR$/Trust/Settings/ViewControllers/SettingsViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Settings/ViewModels/SettingsViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Settings/ViewModels/SettingsViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Tokens/ViewControllers/NewTokenViewController.swift" afterPath="$PROJECT_DIR$/Trust/Tokens/ViewControllers/NewTokenViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Tokens/ViewControllers/TokensViewController.swift" afterPath="$PROJECT_DIR$/Trust/Tokens/ViewControllers/TokensViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transactions/ViewControllers/TransactionViewController.swift" afterPath="$PROJECT_DIR$/Trust/Transactions/ViewControllers/TransactionViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Transactions/ViewModels/TransactionDetailsViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transactions/ViewModels/TransactionsViewModel.swift" afterPath="$PROJECT_DIR$/Trust/Transactions/ViewModels/TransactionsViewModel.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transfer/Types/GasLimitConfiguration.swift" afterPath="$PROJECT_DIR$/Trust/Transfer/Types/GasLimitConfiguration.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transfer/Types/GasPriceConfiguration.swift" afterPath="$PROJECT_DIR$/Trust/Transfer/Types/GasPriceConfiguration.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transfer/ViewControllers/ConfigureTransactionViewController.swift" afterPath="$PROJECT_DIR$/Trust/Transfer/ViewControllers/ConfigureTransactionViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transfer/ViewControllers/SendViewController.swift" afterPath="$PROJECT_DIR$/Trust/Transfer/ViewControllers/SendViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Wallet/ViewControllers/ImportWalletViewController.swift" afterPath="$PROJECT_DIR$/Trust/Wallet/ViewControllers/ImportWalletViewController.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Coordinators/InCoordinatorTests.swift" afterPath="$PROJECT_DIR$/TrustTests/Coordinators/InCoordinatorTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Info.plist" afterPath="$PROJECT_DIR$/TrustTests/Info.plist" />
<change beforePath="$PROJECT_DIR$/TrustTests/Market/OrderSigningTests.swift" afterPath="$PROJECT_DIR$/TrustTests/Market/OrderSigningTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Settings/ConfigTests.swift" afterPath="$PROJECT_DIR$/TrustTests/Settings/ConfigTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Transfer/Types/GasLimitConfigurationTests.swift" afterPath="$PROJECT_DIR$/TrustTests/Transfer/Types/GasLimitConfigurationTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Transfer/Types/GasPriceConfigurationTests.swift" afterPath="$PROJECT_DIR$/TrustTests/Transfer/Types/GasPriceConfigurationTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustUITests/Info.plist" afterPath="$PROJECT_DIR$/TrustUITests/Info.plist" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/Coordinators/BrowserCoordinator.swift" afterPath="$PROJECT_DIR$/Trust/Browser/Coordinators/BrowserCoordinator.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/Types/DappAction.swift" afterPath="$PROJECT_DIR$/Trust/Browser/Types/DappAction.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/Types/DappCommand.swift" afterPath="$PROJECT_DIR$/Trust/Browser/Types/DappCommand.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Browser/ViewControllers/BrowserViewController.swift" afterPath="$PROJECT_DIR$/Trust/Browser/ViewControllers/BrowserViewController.swift" />
<change beforePath="$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift" afterPath="$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift" />
<change beforePath="$PROJECT_DIR$/Trust/EtherClient/KeyStoreError.swift" afterPath="$PROJECT_DIR$/Trust/EtherClient/KeyStoreError.swift" />
<change beforePath="$PROJECT_DIR$/Trust/EtherClient/Keystore.swift" afterPath="$PROJECT_DIR$/Trust/EtherClient/Keystore.swift" />
<change beforePath="$PROJECT_DIR$/Trust/Transfer/Coordinators/SignMessageCoordinator.swift" afterPath="$PROJECT_DIR$/Trust/Transfer/Coordinators/SignMessageCoordinator.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/EtherClient/EtherKeystoreTests.swift" afterPath="$PROJECT_DIR$/TrustTests/EtherClient/EtherKeystoreTests.swift" />
<change beforePath="$PROJECT_DIR$/TrustTests/Factories/FakeKeystore.swift" afterPath="$PROJECT_DIR$/TrustTests/Factories/FakeKeystore.swift" />
</list>
<ignored path="$USER_HOME$/Library/Developer/Xcode/DerivedData/Trust-fagtjernnlugowdujijvfmqpxdjn/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
@ -78,8 +27,8 @@
<file leaf-file-name="SignOrders.swift" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/Trust/Market/SignOrders.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="224">
<caret line="97" column="0" lean-forward="false" selection-start-line="97" selection-start-column="0" selection-end-line="97" selection-end-column="0" />
<state relative-caret-position="300">
<caret line="20" column="45" lean-forward="false" selection-start-line="20" selection-start-column="45" selection-end-line="20" selection-end-column="45" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
@ -87,11 +36,21 @@
</provider>
</entry>
</file>
<file leaf-file-name="OrderSigningTests.swift" pinned="false" current-in-tab="true">
<file leaf-file-name="EtherKeystore.swift" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="431">
<caret line="235" column="45" lean-forward="true" selection-start-line="235" selection-start-column="45" selection-end-line="235" selection-end-column="45" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="OrderSigningTests.swift" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/TrustTests/Market/OrderSigningTests.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="435">
<caret line="29" column="75" lean-forward="true" selection-start-line="29" selection-start-column="75" selection-end-line="29" selection-end-column="75" />
<state relative-caret-position="450">
<caret line="30" column="22" lean-forward="false" selection-start-line="30" selection-start-column="22" selection-end-line="30" selection-end-column="22" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
@ -156,9 +115,9 @@
<option value="$PROJECT_DIR$/TrustTests/TrustTests.swift" />
<option value="$PROJECT_DIR$/Trust/EtherClient/Keystore.swift" />
<option value="$PROJECT_DIR$/Trust/EtherClient/KeyStoreError.swift" />
<option value="$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift" />
<option value="$PROJECT_DIR$/Trust/Market/SignOrders.swift" />
<option value="$PROJECT_DIR$/TrustTests/Market/OrderSigningTests.swift" />
<option value="$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift" />
</list>
</option>
</component>
@ -246,6 +205,12 @@
<item name="Trust" type="1d218c8b:XcodeProjectNode" />
<item name="Trust" type="fcab9f18:XcodeViewNode" />
</path>
<path>
<item name="" type="efc3779f:XcodeRootNode" />
<item name="Trust" type="1d218c8b:XcodeProjectNode" />
<item name="Trust" type="fcab9f18:XcodeViewNode" />
<item name="EtherClient" type="fcab9f18:XcodeViewNode" />
</path>
</expand>
<select />
</subPane>
@ -355,7 +320,7 @@
</history-entry>
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="81764000" />
<option name="totallyTimeSpent" value="81895000" />
</component>
<component name="ToolWindowManager">
<frame x="1280" y="23" width="2560" height="1349" extended-state="0" />
@ -762,18 +727,10 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="213">
<caret line="302" column="9" lean-forward="false" selection-start-line="302" selection-start-column="9" selection-end-line="302" selection-end-column="9" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Trust/Market/SignOrders.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="224">
<caret line="97" column="0" lean-forward="false" selection-start-line="97" selection-start-column="0" selection-end-line="97" selection-end-column="0" />
<state relative-caret-position="300">
<caret line="20" column="45" lean-forward="false" selection-start-line="20" selection-start-column="45" selection-end-line="20" selection-end-column="45" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
@ -782,13 +739,21 @@
</entry>
<entry file="file://$PROJECT_DIR$/TrustTests/Market/OrderSigningTests.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="435">
<caret line="29" column="75" lean-forward="true" selection-start-line="29" selection-start-column="75" selection-end-line="29" selection-end-column="75" />
<state relative-caret-position="450">
<caret line="30" column="22" lean-forward="false" selection-start-line="30" selection-start-column="22" selection-end-line="30" selection-end-column="22" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Trust/EtherClient/EtherKeystore.swift">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="431">
<caret line="235" column="45" lean-forward="true" selection-start-line="235" selection-start-column="45" selection-end-line="235" selection-end-column="45" />
<folding />
</state>
</provider>
</entry>
</component>
</project>

@ -80,6 +80,33 @@ class BrowserCoordinator: Coordinator {
coordinator.start()
navigationController.present(coordinator.navigationController, animated: true, completion: nil)
}
func signMessage(with type: SignMesageType, account: Account, callbackID: Int) {
let coordinator = SignMessageCoordinator(
navigationController: navigationController,
keystore: keystore,
account: account
)
coordinator.didComplete = { [unowned self] result in
switch result {
case .success(let data):
let callback: DappCallback
switch type {
case .message:
callback = DappCallback(id: callbackID, value: .signMessage(data))
case .personalMessage:
callback = DappCallback(id: callbackID, value: .signPersonalMessage(data))
}
self.rootViewController.notifyFinish(callbackID: callbackID, value: .success(callback))
case .failure:
self.rootViewController.notifyFinish(callbackID: callbackID, value: .failure(DAppError.cancelled))
}
self.removeCoordinator(coordinator)
}
coordinator.delegate = self
addCoordinator(coordinator)
coordinator.start(with: type)
}
}
extension BrowserCoordinator: BrowserViewControllerDelegate {
@ -92,27 +119,9 @@ extension BrowserCoordinator: BrowserViewControllerDelegate {
case .sendTransaction(let unconfirmedTransaction):
executeTransaction(account: account, action: action, callbackID: callbackID, transaction: unconfirmedTransaction, type: .signThenSend)
case .signMessage(let hexMessage):
let data = Data(hexString: hexMessage)!
let message = String(data: data, encoding: .utf8)!
let coordinator = SignMessageCoordinator(
navigationController: navigationController,
keystore: keystore,
account: account
)
coordinator.didComplete = { [unowned self] result in
switch result {
case .success(let data):
let callback = DappCallback(id: callbackID, value: .signMessage(data))
self.rootViewController.notifyFinish(callbackID: callbackID, value: .success(callback))
case .failure:
self.rootViewController.notifyFinish(callbackID: callbackID, value: .failure(DAppError.cancelled))
}
self.removeCoordinator(coordinator)
}
coordinator.delegate = self
addCoordinator(coordinator)
coordinator.start(with: message)
signMessage(with: .message(Data(hex: hexMessage)), account: account, callbackID: callbackID)
case .signPersonalMessage(let hexMessage):
signMessage(with: .personalMessage(Data(hex: hexMessage)), account: account, callbackID: callbackID)
case .unknown:
break
}

@ -6,6 +6,7 @@ import TrustKeystore
enum DappAction {
case signMessage(String)
case signPersonalMessage(String)
case signTransaction(UnconfirmedTransaction)
case sendTransaction(UnconfirmedTransaction)
case unknown
@ -13,15 +14,19 @@ enum DappAction {
extension DappAction {
static func fromCommand(_ command: DappCommand) -> DappAction {
NSLog("command.name \(command.name)")
NSLog("command.object \(command.object)")
switch command.name {
case .signTransaction:
return .signTransaction(DappAction.makeUnconfirmedTransaction(command.object))
case .sendTransaction:
return .sendTransaction(DappAction.makeUnconfirmedTransaction(command.object))
case .signMessage, .signPersonalMessage:
NSLog("command.object \(command.object)")
case .signMessage:
let data = command.object["data"]?.value ?? ""
return .signMessage(data)
case .signPersonalMessage:
let data = command.object["data"]?.value ?? ""
return .signPersonalMessage(data)
case .unknown:
return .unknown
}

@ -17,6 +17,7 @@ enum DappCallbackValue {
case signTransaction(Data)
case sentTransaction(Data)
case signMessage(Data)
case signPersonalMessage(Data)
var object: String {
switch self {
@ -26,6 +27,8 @@ enum DappCallbackValue {
return data.hexEncoded
case .signMessage(let data):
return data.hexEncoded
case .signPersonalMessage(let data):
return data.hexEncoded
}
}
}

@ -208,7 +208,6 @@ extension BrowserViewController: WKNavigationDelegate {
extension BrowserViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let method = Method(string: message.name)
guard let body = message.body as? [String: AnyObject],
let jsonString = body.jsonString,
let command = try? decoder.decode(DappCommand.self, from: jsonString.data(using: .utf8)!) else {
@ -216,11 +215,6 @@ extension BrowserViewController: WKScriptMessageHandler {
}
let action = DappAction.fromCommand(command)
switch method {
case .sendTransaction, .signTransaction, .signPersonalMessage:
delegate?.didCall(action: action, callbackID: command.id)
case .signMessage, .unknown:
break
}
delegate?.didCall(action: action, callbackID: command.id)
}
}

@ -235,13 +235,26 @@ open class EtherKeystore: Keystore {
guard let account = getAccount(for: account.address) else {
return .failure(.accountNotFound)
}
do {
let data = try keyStore.export(account: account, password: password, newPassword: newPassword)
return (.success(data))
} catch {
return (.failure(.failedToDecryptKey))
}
}
func exportPrivateKey(account: Account) -> Result<Data, KeystoreError> {
guard let password = getPassword(for: account) else {
return .failure(KeystoreError.accountNotFound)
}
do {
let privateKey = try keyStore.exportPrivateKey(account: account, password: password)
return .success(privateKey)
} catch {
return .failure(KeystoreError.failedToExportPrivateKey)
}
}
func delete(wallet: Wallet) -> Result<Void, KeystoreError> {
@ -289,20 +302,20 @@ open class EtherKeystore: Keystore {
}
}
func signPersonalMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError> {
func signPersonalMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError> {
let message = String(data: data, encoding: .utf8)!
let formattedMessage: String = "\u{19}Ethereum Signed Message:\n" + "\(message.count)" + message
return signMessage(formattedMessage, for: account)
let hash = formattedMessage.data(using: .utf8)?.sha3(.keccak256)
return signMessage(hash!, for: account)
}
//this method is no good unless message is a plain string, should be replaced with signMessageData below
public func signMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError> {
func signMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError> {
guard
let hash = message.data(using: .utf8)?.sha3(.keccak256),
let password = getPassword(for: account) else {
return .failure(KeystoreError.failedToSignMessage)
}
do {
var data = try keyStore.signHash(hash, account: account, password: password)
var data = try keyStore.signHash(data, account: account, password: password)
// TODO: Make it configurable, instead of overriding last byte.
data[64] += 27
return .success(data)

@ -14,6 +14,7 @@ public enum KeystoreError: LocalizedError {
case failedToParseJSON
case accountNotFound
case failedToSignMessage
case failedToExportPrivateKey
public var errorDescription: String? {
switch self {
@ -39,6 +40,8 @@ public enum KeystoreError: LocalizedError {
return "Account not found"
case .failedToSignMessage:
return "Failed to sign message"
case .failedToExportPrivateKey:
return "Failed to export private key"
}
}
}

@ -23,8 +23,8 @@ protocol Keystore {
func delete(wallet: Wallet) -> Result<Void, KeystoreError>
func delete(wallet: Wallet, completion: @escaping (Result<Void, KeystoreError>) -> Void)
func updateAccount(account: Account, password: String, newPassword: String) -> Result<Void, KeystoreError>
func signPersonalMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError>
func signMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError>
func signPersonalMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError>
func signMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError>
func signTransaction(_ signTransaction: SignTransaction) -> Result<Data, KeystoreError>
func getPassword(for account: Account) -> String?
func convertPrivateKeyToKeystoreFile(privateKey: String, passphrase: String) -> Result<[String: Any], KeystoreError>

@ -6,6 +6,11 @@ import TrustKeystore
import CryptoSwift
import Result
enum SignMesageType {
case message(Data)
case personalMessage(Data)
}
protocol SignMessageCoordinatorDelegate: class {
func didCancel(in coordinator: SignMessageCoordinator)
}
@ -31,16 +36,15 @@ class SignMessageCoordinator: Coordinator {
self.account = account
}
func start(with message: String) {
let alertController = makeAlertController(message: message)
func start(with type: SignMesageType) {
let alertController = makeAlertController(with: type)
navigationController.present(alertController, animated: true, completion: nil)
}
private func makeAlertController(message: String) -> UIAlertController {
private func makeAlertController(with type: SignMesageType) -> UIAlertController {
let alertController = UIAlertController(
title: NSLocalizedString("", value: "Confirm signing this message:", comment: ""),
message: message,
message: message(for: type),
preferredStyle: .alert
)
let signAction = UIAlertAction(
@ -48,7 +52,7 @@ class SignMessageCoordinator: Coordinator {
style: .default
) { [weak self] _ in
guard let `self` = self else { return }
self.handleSignedPersonalMessage(message: message)
self.handleSignedMessage(with: type)
}
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", value: "Cancel", comment: ""), style: .cancel) { [weak self] _ in
guard let `self` = self else { return }
@ -60,8 +64,23 @@ class SignMessageCoordinator: Coordinator {
return alertController
}
private func handleSignedPersonalMessage(message: String) {
let result = self.keystore.signPersonalMessage(message, for: self.account)
func message(for type: SignMesageType) -> String {
switch type {
case .message(let data):
return data.hexEncoded
case .personalMessage(let data):
return String(data: data, encoding: .utf8)!
}
}
private func handleSignedMessage(with type: SignMesageType) {
let result: Result<Data, KeystoreError>
switch type {
case .message(let data):
result = keystore.signMessage(data, for: account)
case .personalMessage(let data):
result = keystore.signPersonalMessage(data, for: account)
}
switch result {
case .success(let data):
didComplete?(.success(data))

@ -204,7 +204,7 @@ class EtherKeystoreTests: XCTestCase {
XCTAssertEqual(1, keystore.wallets.count)
}
func testSignMessage() {
func testSignPersonalMessage() {
let keystore = FakeEtherKeystore()
let privateKeyResult = keystore.convertPrivateKeyToKeystoreFile(privateKey: "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318", passphrase: TestKeyStore.password)
@ -223,7 +223,7 @@ class EtherKeystoreTests: XCTestCase {
return XCTFail()
}
let signResult = keystore.signPersonalMessage("Some data", for: account)
let signResult = keystore.signPersonalMessage("Some data".data(using: .utf8)!, for: account)
guard case let .success(data) = signResult else {
return XCTFail()
@ -243,6 +243,36 @@ class EtherKeystoreTests: XCTestCase {
// signature: '0xb91467e570a6466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a0291c'
}
func testSignMessage() {
let keystore = FakeEtherKeystore()
let privateKeyResult = keystore.convertPrivateKeyToKeystoreFile(privateKey: "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318", passphrase: TestKeyStore.password)
guard case let .success(keystoreString) = privateKeyResult else {
return XCTFail()
}
let result = keystore.importKeystore(
value: keystoreString.jsonString!,
password: TestKeyStore.password,
newPassword: TestKeyStore.password
)
guard case let .success(account) = result else {
return XCTFail()
}
let signResult = keystore.signPersonalMessage("0x3f44c2dfea365f01c1ada3b7600db9e2999dfea9fe6c6017441eafcfbc06a543".data(using: .utf8)!, for: account)
guard case let .success(data) = signResult else {
return XCTFail()
}
let expected = Data(hexString: "0x619b03743672e31ad1d7ee0e43f6802860082d161acc602030c495a12a68b791666764ca415a2b3083595aee448402874a5a376ea91855051e04c7b3e4693d201c")
XCTAssertEqual(expected, data)
}
func testAddWatchAddress() {
let keystore = FakeEtherKeystore()
let address: Address = .make()

@ -78,11 +78,11 @@ struct FakeKeystore: Keystore {
return .failure(KeystoreError.failedToSignTransaction)
}
func signPersonalMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError> {
func signPersonalMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError> {
return .failure(KeystoreError.failedToSignTransaction)
}
func signMessage(_ message: String, for account: Account) -> Result<Data, KeystoreError> {
func signMessage(_ data: Data, for account: Account) -> Result<Data, KeystoreError> {
return .failure(KeystoreError.failedToSignMessage)
}

Loading…
Cancel
Save