Skip to content
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

Message signing #23

Merged
merged 6 commits into from
Jan 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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