Skip to content

Commit

Permalink
Merge pull request #23 from WalletConnect/message-signing
Browse files Browse the repository at this point in the history
Message signing
  • Loading branch information
llbartekll committed Jan 17, 2022
2 parents a84f3b0 + 362239d commit b02dd1e
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 39 deletions.
26 changes: 26 additions & 0 deletions Example/ExampleApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
76744CF526FDFB6B00B77ED9 /* ResponderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76744CF426FDFB6B00B77ED9 /* ResponderView.swift */; };
76744CF726FE4D5400B77ED9 /* ActiveSessionItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76744CF626FE4D5400B77ED9 /* ActiveSessionItem.swift */; };
76744CF926FE4D7400B77ED9 /* ActiveSessionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76744CF826FE4D7400B77ED9 /* ActiveSessionCell.swift */; };
84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; };
844943A1278EC49700CC26BB /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = 844943A0278EC49700CC26BB /* Web3 */; };
845B30EF27859686002E4094 /* ExampleAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B30EE27859686002E4094 /* ExampleAppTests.swift */; };
8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFB274F98A10081F94C /* RequestViewController.swift */; };
8460DD002750D6F50081F94C /* SessionDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFF2750D6F50081F94C /* SessionDetailsViewController.swift */; };
Expand Down Expand Up @@ -58,6 +60,7 @@
76744CF426FDFB6B00B77ED9 /* ResponderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponderView.swift; sourceTree = "<group>"; };
76744CF626FE4D5400B77ED9 /* ActiveSessionItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveSessionItem.swift; sourceTree = "<group>"; };
76744CF826FE4D7400B77ED9 /* ActiveSessionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveSessionCell.swift; sourceTree = "<group>"; };
84494387278D9C1B00CC26BB /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = "<group>"; };
845B30EC27859686002E4094 /* ExampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
845B30EE27859686002E4094 /* ExampleAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleAppTests.swift; sourceTree = "<group>"; };
8460DCFB274F98A10081F94C /* RequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestViewController.swift; sourceTree = "<group>"; };
Expand All @@ -71,6 +74,7 @@
buildActionMask = 2147483647;
files = (
764E1D5826F8DBAB00A1FB15 /* WalletConnect in Frameworks */,
844943A1278EC49700CC26BB /* Web3 in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -88,6 +92,7 @@
isa = PBXGroup;
children = (
761C649B26FB7B7F004239D1 /* ResponderViewController.swift */,
84494387278D9C1B00CC26BB /* UIAlertController.swift */,
76744CF426FDFB6B00B77ED9 /* ResponderView.swift */,
76744CF826FE4D7400B77ED9 /* ActiveSessionCell.swift */,
76744CF626FE4D5400B77ED9 /* ActiveSessionItem.swift */,
Expand Down Expand Up @@ -204,6 +209,7 @@
name = ExampleApp;
packageProductDependencies = (
764E1D5726F8DBAB00A1FB15 /* WalletConnect */,
844943A0278EC49700CC26BB /* Web3 */,
);
productName = ExampleApp;
productReference = 764E1D3C26F8D3FC00A1FB15 /* ExampleApp.app */;
Expand Down Expand Up @@ -254,6 +260,9 @@
Base,
);
mainGroup = 764E1D3326F8D3FC00A1FB15;
packageReferences = (
8449439F278EC49700CC26BB /* XCRemoteSwiftPackageReference "Web3" */,
);
productRefGroup = 764E1D3D26F8D3FC00A1FB15 /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down Expand Up @@ -303,6 +312,7 @@
8460DD022750D7020081F94C /* SessionDetailsView.swift in Sources */,
7603D74D2703429A00DD27A2 /* ProposerView.swift in Sources */,
764E1D5A26F8DF1B00A1FB15 /* ScannerViewController.swift in Sources */,
84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -572,11 +582,27 @@
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
8449439F278EC49700CC26BB /* XCRemoteSwiftPackageReference "Web3" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Boilertalk/Web3.swift";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.5.3;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
764E1D5726F8DBAB00A1FB15 /* WalletConnect */ = {
isa = XCSwiftPackageProductDependency;
productName = WalletConnect;
};
844943A0278EC49700CC26BB /* Web3 */ = {
isa = XCSwiftPackageProductDependency;
package = 8449439F278EC49700CC26BB /* XCRemoteSwiftPackageReference "Web3" */;
productName = Web3;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 764E1D3426F8D3FC00A1FB15 /* Project object */;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "BigInt",
"repositoryURL": "https://github.com/attaswift/BigInt.git",
"state": {
"branch": null,
"revision": "0ed110f7555c34ff468e72e1686e59721f2b0da6",
"version": "5.3.0"
}
},
{
"package": "CryptoSwift",
"repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift.git",
Expand All @@ -9,6 +18,33 @@
"revision": "4b0565384d3c4c588af09e660535b2c7c9bf5b39",
"version": "1.4.2"
}
},
{
"package": "PromiseKit",
"repositoryURL": "https://github.com/mxcl/PromiseKit.git",
"state": {
"branch": null,
"revision": "93c8d41ce96ed78f36c3948be396d76f3ca3de1b",
"version": "6.16.2"
}
},
{
"package": "secp256k1",
"repositoryURL": "https://github.com/Boilertalk/secp256k1.swift.git",
"state": {
"branch": null,
"revision": "823281fe9def21b384099b72a9a53ca988317b20",
"version": "0.1.4"
}
},
{
"package": "Web3",
"repositoryURL": "https://github.com/Boilertalk/Web3.swift",
"state": {
"branch": null,
"revision": "1a6830ecc093f0f19054fed4c135dfee7bebe2b2",
"version": "0.5.3"
}
}
]
},
Expand Down
6 changes: 3 additions & 3 deletions Example/ExampleApp/Proposer/ProposerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ final class ProposerViewController: UIViewController {
icons: ["https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"])
return WalletConnectClient(
metadata: metadata,
projectId: "",
isController: false,
relayHost: "relay.walletconnect.org",
projectId: "52af113ee0c1e1a20f4995730196c13e",
isController: true,
relayHost: "relay.dev.walletconnect.com",
clientName: "proposer"
)
}()
Expand Down
23 changes: 16 additions & 7 deletions Example/ExampleApp/Responder/Request/RequestViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Foundation
import UIKit
import WalletConnect
import Web3

class RequestViewController: UIViewController {
var onSign: (()->())?
Expand All @@ -23,13 +24,8 @@ class RequestViewController: UIViewController {
super.viewDidLoad()
requestView.approveButton.addTarget(self, action: #selector(signAction), for: .touchUpInside)
requestView.rejectButton.addTarget(self, action: #selector(rejectAction), for: .touchUpInside)
let method = sessionRequest.method
requestView.nameLabel.text = method
var paramsDescription = ""
if method == "personal_sign" {
paramsDescription = try! sessionRequest.params.get([String].self).description
}
requestView.descriptionLabel.text = paramsDescription
requestView.nameLabel.text = sessionRequest.method
requestView.descriptionLabel.text = getParamsDescription()
}

required init?(coder: NSCoder) {
Expand All @@ -47,6 +43,19 @@ class RequestViewController: UIViewController {
onReject?()
dismiss(animated: true)
}

private func getParamsDescription() -> String {
let method = sessionRequest.method
if method == "personal_sign" {
return try! sessionRequest.params.get([String].self).description
} else if method == "eth_signTypedData" {
return try! sessionRequest.params.get([String].self).description
} else if method == "eth_sendTransaction" {
let params = try! sessionRequest.params.get([EthereumTransaction].self)
return params[0].description
}
fatalError("not implemented")
}
}

final class RequestView: UIView {
Expand Down
89 changes: 64 additions & 25 deletions Example/ExampleApp/Responder/ResponderViewController.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import UIKit
import WalletConnect
import WalletConnectUtils
import Web3
import CryptoSwift

final class ResponderViewController: UIViewController {

Expand All @@ -12,15 +14,16 @@ final class ResponderViewController: UIViewController {
icons: ["https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"])
return WalletConnectClient(
metadata: metadata,
projectId: "",
projectId: "52af113ee0c1e1a20f4995730196c13e",
isController: true,
relayHost: "relay.walletconnect.org",
relayHost: "relay.dev.walletconnect.com",
clientName: "responder"
)
}()
let account = "0x022c0c42a80bd19EA4cF0F94c4F9F96645759716"
lazy var account = privateKey.address.hex(eip55: true)
var sessionItems: [ActiveSessionItem] = []
var currentProposal: Session.Proposal?
let privateKey: EthereumPrivateKey = try! EthereumPrivateKey(hexPrivateKey: "0xe56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540")

private let responderView: ResponderView = {
ResponderView()
Expand Down Expand Up @@ -78,10 +81,10 @@ final class ResponderViewController: UIViewController {

private func showSessionRequest(_ sessionRequest: Request) {
let requestVC = RequestViewController(sessionRequest)
requestVC.onSign = { [weak self] in
let result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
let response = JSONRPCResponse<AnyCodable>(id: sessionRequest.id, result: AnyCodable(result))
self?.client.respond(topic: sessionRequest.topic, response: .response(response))
requestVC.onSign = { [unowned self] in
let result = signEth(request: sessionRequest)
let response = JSONRPCResponse<AnyCodable>(id: sessionRequest.id, result: result)
client.respond(topic: sessionRequest.topic, response: .response(response))
}
requestVC.onReject = { [weak self] in
self?.client.respond(topic: sessionRequest.topic, response: .error(JSONRPCErrorResponse(id: sessionRequest.id, error: JSONRPCErrorResponse.Error(code: 0, message: ""))))
Expand Down Expand Up @@ -224,24 +227,60 @@ extension ResponderViewController: WalletConnectClientDelegate {
self.responderView.tableView.reloadData()
}
}
}

extension UIAlertController {

static func createInputAlert(confirmHandler: @escaping (String) -> Void) -> UIAlertController {
let alert = UIAlertController(title: "Paste URI", message: "Enter a WalletConnect URI to connect.", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
let confirmAction = UIAlertAction(title: "Connect", style: .default) { _ in
if let input = alert.textFields?.first?.text, !input.isEmpty {
confirmHandler(input)
}
}
alert.addTextField { textField in
textField.placeholder = "wc://a14aefb980188fc35ec9..."

func signEth(request: Request) -> AnyCodable {
let method = request.method
if method == "personal_sign" {
let params = try! request.params.get([String].self)
let messageToSign = params[0]
let signHash = signHash(messageToSign)
let (v, r, s) = try! self.privateKey.sign(hash: signHash)
let result = "0x" + r.toHexString() + s.toHexString() + String(v + 27, radix: 16)
return AnyCodable(result)
} else if method == "eth_signTypedData" {
let params = try! request.params.get([String].self)
print(params)
let messageToSign = params[1]
let signHash = signHash(messageToSign)
let (v, r, s) = try! self.privateKey.sign(hash: signHash)
let result = "0x" + r.toHexString() + s.toHexString() + String(v + 27, radix: 16)
return AnyCodable(result)
} else if method == "eth_sendTransaction" {
let params = try! request.params.get([EthereumTransaction].self)
var transaction = params[0]
transaction.gas = EthereumQuantity(quantity: BigUInt("1234"))
print(transaction.description)
let signedTx = try! transaction.sign(with: self.privateKey, chainId: 4)
let (r, s, v) = (signedTx.r, signedTx.s, signedTx.v)
let result = r.hex() + s.hex().dropFirst(2) + String(v.quantity, radix: 16)
return AnyCodable(result)
} else {
print("TODO")
}
alert.addAction(cancelAction)
alert.addAction(confirmAction)
alert.preferredAction = confirmAction
return alert
fatalError()
}

func signHash(_ message: String) -> Bytes {
let prefix = "\u{19}Ethereum Signed Message:\n"
let messageData = Data(hex: message)
let prefixData = (prefix + String(messageData.count)).data(using: .utf8)!
let prefixedMessageData = prefixData + messageData
let dataToHash: Bytes = .init(hex: prefixedMessageData.toHexString())
return SHA3(variant: .keccak256).calculate(for: dataToHash)
}

}

extension EthereumTransaction {
var description: String {
return """
from: \(String(describing: from!.hex(eip55: true)))
to: \(String(describing: to!.hex(eip55: true))),
value: \(String(describing: value!.hex())),
gasPrice: \(String(describing: gasPrice?.hex())),
gas: \(String(describing: gas?.hex())),
data: \(data.hex()),
nonce: \(String(describing: nonce?.hex()))
"""
}
}
21 changes: 21 additions & 0 deletions Example/ExampleApp/Responder/UIAlertController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import UIKit

extension UIAlertController {

static func createInputAlert(confirmHandler: @escaping (String) -> Void) -> UIAlertController {
let alert = UIAlertController(title: "Paste URI", message: "Enter a WalletConnect URI to connect.", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
let confirmAction = UIAlertAction(title: "Connect", style: .default) { _ in
if let input = alert.textFields?.first?.text, !input.isEmpty {
confirmHandler(input)
}
}
alert.addTextField { textField in
textField.placeholder = "wc://a14aefb980188fc35ec9..."
}
alert.addAction(cancelAction)
alert.addAction(confirmAction)
alert.preferredAction = confirmAction
return alert
}
}
6 changes: 3 additions & 3 deletions Example/ExampleApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ extension UITabBarController {
static func createExampleApp() -> UITabBarController {
let responderController = UINavigationController(rootViewController: ResponderViewController())
responderController.tabBarItem = UITabBarItem(title: "Wallet", image: UIImage(systemName: "dollarsign.circle"), selectedImage: nil)
let proposerController = UINavigationController(rootViewController: ProposerViewController())
proposerController.tabBarItem = UITabBarItem(title: "Dapp", image: UIImage(systemName: "appclip"), selectedImage: nil)
// let proposerController = UINavigationController(rootViewController: ProposerViewController())
// proposerController.tabBarItem = UITabBarItem(title: "Dapp", image: UIImage(systemName: "appclip"), selectedImage: nil)
let tabBarController = UITabBarController()
tabBarController.viewControllers = [responderController, proposerController]
tabBarController.viewControllers = [responderController]
return tabBarController
}
}
2 changes: 1 addition & 1 deletion Sources/Relayer/SocketConnectionObserving.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ protocol SocketConnectionObserving {
var onDisconnect: (()->())? {get set}
}

class SocketConnectionObserver: NSObject, URLSessionDelegate, SocketConnectionObserving {
class SocketConnectionObserver: NSObject, URLSessionWebSocketDelegate, SocketConnectionObserving {
var onConnect: (()->())?
var onDisconnect: (()->())?

Expand Down

0 comments on commit b02dd1e

Please sign in to comment.