From daa25e1f948f490c63a2e29c516c9f16e9ef2820 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 15 Jun 2022 18:13:07 +0500 Subject: [PATCH] Add Swiftlint (#271) Swiftlint default rules applied --- .swiftlint.yml | 20 +++++ Example/DApp/ Accounts/AccountsView.swift | 8 +- .../ Accounts/AccountsViewController.swift | 34 ++++----- .../AccountRequest/AccountRequestView.swift | 17 ++--- .../AccountRequestViewController.swift | 31 ++++---- Example/DApp/AppDelegate.swift | 2 - Example/DApp/Connect/ConnectView.swift | 20 +++-- .../DApp/Connect/ConnectViewController.swift | 24 +++--- Example/DApp/ResponseViewController.swift | 29 ++++---- Example/DApp/SceneDelegate.swift | 14 ++-- .../DApp/SelectChain/SelectChainView.swift | 13 ++-- .../SelectChainViewController.swift | 12 ++- Example/ExampleApp/Request/RequestView.swift | 32 ++++---- .../Request/RequestViewController.swift | 15 ++-- Example/ExampleApp/SceneDelegate.swift | 14 ++-- .../SessionDetails/SessionDetailView.swift | 38 +++++----- .../SessionDetailViewController.swift | 14 ++-- .../SessionDetailViewModel.swift | 33 ++++----- .../SessionDetailsViewController.swift | 36 ++++----- .../SessionNamespaceViewModel.swift | 2 +- .../ExampleApp/SessionProposal/Proposal.swift | 8 +- .../SessionProposal/ProposalView.swift | 20 ++--- .../ProposalViewController.swift | 10 +-- Example/ExampleApp/Shared/Array.swift | 2 +- .../ExampleApp/Shared/Color+Extension.swift | 6 +- .../Shared/EthereumTransaction.swift | 1 - Example/ExampleApp/Shared/Signer.swift | 6 +- .../ExampleApp/Shared/UIAlertController.swift | 2 +- .../ExampleApp/Shared/UIKit+Previews.swift | 4 +- Example/ExampleApp/Shared/Utilities.swift | 2 +- .../ExampleApp/Wallet/ActiveSessionCell.swift | 24 +++--- .../Wallet/ScannerViewController.swift | 18 ++--- Example/ExampleApp/Wallet/WalletView.swift | 24 +++--- .../Wallet/WalletViewController.swift | 42 +++++------ Example/UITests/Engine/App.swift | 6 +- Example/UITests/Engine/DAppEngine.swift | 20 ++--- Example/UITests/Engine/Engine.swift | 2 +- Example/UITests/Engine/RoutingEngine.swift | 8 +- Example/UITests/Engine/SafariEngine.swift | 2 +- Example/UITests/Engine/WalletEngine.swift | 22 +++--- Example/UITests/Extensions/XCUIElement.swift | 6 +- .../UITests/Regression/RegressionTests.swift | 18 ++--- Package.swift | 8 +- Sources/Chat/Chat.swift | 27 +++---- Sources/Chat/Engine.swift | 8 +- Sources/Chat/NetworkingInteractor.swift | 34 ++++----- Sources/Chat/Registry.swift | 10 +-- Sources/Chat/RegistryManager.swift | 5 +- Sources/Chat/Serializing.swift | 1 - Sources/Chat/StorageDomainIdentifiers.swift | 1 - Sources/Chat/Types/ChatError.swift | 1 - Sources/Chat/Types/ChatRequest.swift | 16 ++-- Sources/Chat/Types/ChatResponse.swift | 2 - Sources/Chat/Types/Invite.swift | 6 +- .../Types/RequestSubscriptionPayload.swift | 2 - Sources/Chat/Types/Thread.swift | 4 +- Sources/Commons/AnyCodable.swift | 40 +++++----- Sources/JSONRPC/JSONRPCError.swift | 2 +- Sources/JSONRPC/RPCID.swift | 2 +- Sources/JSONRPC/RPCRequest.swift | 36 ++++----- Sources/JSONRPC/RPCResponse.swift | 32 ++++---- .../Codec/ChaChaPolyCodec.swift | 2 +- .../Crypto/AgreementKeys.swift | 8 +- .../CryptoKitWrapper/CryptoKitWrapper.swift | 28 +++---- .../CryptoKitWrapper/SharedSecret.swift | 5 +- .../Crypto/KeyManagementService.swift | 38 +++++----- .../Crypto/SymmetricKey.swift | 17 ++--- .../Keychain/KeychainError.swift | 6 +- .../Keychain/KeychainService.swift | 8 +- .../Keychain/KeychainStorage.swift | 46 ++++++------ .../Serialiser/Serializer.swift | 12 ++- .../AppStateObserving.swift | 23 +++--- Sources/WalletConnectRelay/Dispatching.swift | 34 ++++----- .../Misc/NetworkError.swift | 2 +- .../NetworkMonitoring.swift | 14 ++-- Sources/WalletConnectRelay/RelayClient.swift | 44 ++++++----- Sources/WalletConnectRelay/RelayJSONRPC.swift | 10 +-- .../AutomaticSocketConnectionHandler.swift | 17 ++--- .../BackgroundTaskRegistering.swift | 7 +- .../ManualSocketConnectionHandler.swift | 5 +- .../SocketConnectionHandler.swift | 1 - .../SocketConnectionType.swift | 1 - .../WebSocketConnecting.swift | 2 +- .../WebSocketProtocol.swift | 11 ++- .../WalletConnectSign/Constants/Time.swift | 6 +- .../Engine/Common/ApproveEngine.swift | 73 +++++++++---------- .../Engine/Common/PairingEngine.swift | 30 ++++---- .../Engine/Common/SessionEngine.swift | 50 ++++++------- .../ControllerSessionStateMachine.swift | 29 ++++---- .../Engine/Controller/PairEngine.swift | 7 +- .../NonControllerSessionStateMachine.swift | 11 ++- .../JsonRpcHistory/JsonRpcHistory.swift | 19 +++-- .../JsonRpcHistory/JsonRpcRecord.swift | 3 - Sources/WalletConnectSign/Namespace.swift | 22 +++--- .../NetworkInteractor/NetworkInteractor.swift | 54 +++++++------- .../NetworkInteractor/NetworkRelaying.swift | 11 ++- Sources/WalletConnectSign/Reason.swift | 4 +- .../WalletConnectSign/RejectionReason.swift | 1 - Sources/WalletConnectSign/Request.swift | 6 +- Sources/WalletConnectSign/Response.swift | 1 - Sources/WalletConnectSign/Serializing.swift | 1 - .../Services/CelanupService.swift | 6 +- Sources/WalletConnectSign/Session.swift | 10 +-- Sources/WalletConnectSign/Sign/Sign.swift | 67 +++++++++-------- .../WalletConnectSign/Sign/SignClient.swift | 57 +++++++-------- .../Sign/SignClientDelegate.swift | 19 +++-- .../WalletConnectSign/Sign/SignConfig.swift | 2 +- .../Storage/PairingStorage.swift | 18 ++--- .../Storage/SequenceStore.swift | 10 +-- .../Storage/SessionStorage.swift | 18 ++--- .../StorageDomainIdentifiers.swift | 1 - .../WCRequestSubscriptionPayload.swift | 1 - .../Types/Common/AppMetadata.swift | 11 ++- .../Types/Common/Participant.swift | 3 +- .../Types/Common/RelayProtocolOptions.swift | 1 - .../Types/Pairing/PairingProposal.swift | 3 - .../Types/Pairing/PairingType.swift | 5 +- .../Types/Pairing/WCPairing.swift | 16 ++-- .../WalletConnectSign/Types/ReasonCode.swift | 22 +++--- .../Types/Session/SessionProposal.swift | 3 +- .../Types/Session/SessionType.swift | 26 +++---- .../Types/Session/WCSession.swift | 22 +++--- .../WalletConnectSign/Types/WCMethod.swift | 2 +- .../WalletConnectSign/Types/WCRequest.swift | 8 +- .../Types/WalletConnectURI.swift | 12 +-- .../WalletConnectError.swift | 10 +-- Sources/WalletConnectUtils/Account.swift | 22 +++--- Sources/WalletConnectUtils/Blockchain.swift | 14 ++-- Sources/WalletConnectUtils/CodableStore.swift | 9 +-- .../WalletConnectUtils/Data+Extension.swift | 2 +- Sources/WalletConnectUtils/Encodable.swift | 2 +- .../Extensions/String+Extension.swift | 6 +- .../Extensions/String.swift | 8 +- .../JSONRPC/JSONRPCErrorResponse.swift | 3 +- .../JSONRPC/JSONRPCRequest.swift | 6 +- .../JSONRPC/JSONRPCResponse.swift | 1 - .../JSONRPC/JsonRpcResult.swift | 2 - .../WalletConnectUtils/JsonRpcHistory.swift | 15 ++-- .../WalletConnectUtils/JsonRpcRecord.swift | 8 +- .../WalletConnectUtils/KeyValueStorage.swift | 10 +-- Sources/WalletConnectUtils/Logger.swift | 19 +++-- Sources/WalletConnectUtils/Queue.swift | 9 +-- .../TimeInterval+Extension.swift | 6 +- Tests/ChatTests/EndToEndTests.swift | 12 ++- .../Mocks/NetworkingInteractorMock.swift | 3 +- Tests/ChatTests/RegistryManagerTests.swift | 5 +- Tests/CommonsTests/AnyCodableTests.swift | 48 ++++++------ Tests/IntegrationTests/ClientDelegate.swift | 33 ++++----- Tests/IntegrationTests/SerialiserTests.swift | 7 +- Tests/IntegrationTests/SignClientTests.swift | 30 ++++---- Tests/IntegrationTests/XCTestManifests.swift | 2 +- Tests/JSONRPCTests/Data/RequestJSON.swift | 24 +++--- Tests/JSONRPCTests/Data/ResponseJSON.swift | 36 ++++----- Tests/JSONRPCTests/Helpers.swift | 8 +- Tests/JSONRPCTests/RPCRequestTests.swift | 34 ++++----- Tests/JSONRPCTests/RPCResponseTests.swift | 40 +++++----- ...utomaticSocketConnectionHandlerTests.swift | 9 +-- Tests/RelayerTests/DispatcherTests.swift | 12 ++- .../Helpers/Error+Extension.swift | 8 +- .../RelayerTests/Helpers/URL+Extension.swift | 2 +- .../ManualSocketConnectionHandlerTests.swift | 6 +- .../Mocks/AppStateObserverMock.swift | 5 +- .../Mocks/BackgroundTaskRegistrarMock.swift | 5 +- Tests/RelayerTests/Mocks/DispatcherMock.swift | 8 +- .../Mocks/NetworkMonitoringMock.swift | 7 +- .../RelayClientEndToEndTests.swift | 15 ++-- Tests/RelayerTests/WakuRelayTests.swift | 16 ++-- Tests/TestingUtils/ConsoleLoggerMock.swift | 1 - Tests/TestingUtils/Helpers.swift | 10 +-- .../Mocks/KeyManagementServiceMock.swift | 42 +++++------ .../Mocks/KeychainServiceFake.swift | 16 ++-- .../Mocks/KeychainStorageMock.swift | 16 ++-- Tests/TestingUtils/TopicGenerator.swift | 6 +- Tests/TestingUtils/XCTest.swift | 3 +- .../AgreementSecret+Stub.swift | 2 +- .../ChaChaPolyCodec_Test.swift | 7 +- .../KeyManagementServiceTests.swift | 26 +++---- .../KeychainServiceFake.swift | 14 ++-- .../KeychainStorageTests.swift | 36 ++++----- .../WalletConnectSignTests/AccountTests.swift | 22 +++--- .../ApproveEngineTests.swift | 30 ++++---- .../BlockchainTests.swift | 10 +-- .../ControllerSessionStateMachineTests.swift | 25 +++---- .../Helpers/Error+Extension.swift | 12 +-- .../Helpers/TimeTraveler.swift | 8 +- .../JsonRpcHistoryTests.swift | 21 +++--- .../Mocks/MockedRelay.swift | 49 ++++++------- .../Mocks/MockedRelayClient.swift | 22 +++--- .../Mocks/SerializerMock.swift | 9 +-- .../Mocks/WCPairingStorageMock.swift | 14 ++-- .../Mocks/WCSessionStorageMock.swift | 15 ++-- .../NamespaceValidationTests.swift | 58 +++++++-------- ...onControllerSessionStateMachineTests.swift | 37 +++++----- .../PairEngineTests.swift | 18 ++--- .../PairingEngineTests.swift | 53 +++++++------- .../SequenceStoreTests.swift | 60 +++++++-------- .../Stub/AgreementSecret+Stub.swift | 2 +- Tests/WalletConnectSignTests/Stub/Stubs.swift | 8 +- .../Stub/WalletConnectURI+Stub.swift | 2 +- .../WCPairingTests.swift | 16 ++-- .../WalletConnectSignTests/WCRelayTests.swift | 11 ++- .../WCSessionTests.swift | 22 +++--- .../WalletConnectURITests.swift | 22 +++--- .../XCTestManifests.swift | 2 +- .../String+ExtensionTests.swift | 20 ++--- 205 files changed, 1528 insertions(+), 1656 deletions(-) create mode 100644 .swiftlint.yml diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..e25c7e833 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,20 @@ +disabled_rules: + - line_length + - force_try + - force_cast + - todo + - identifier_name + - nesting + - for_where + - large_tuple + - xctfail_message + - redundant_string_enum_value + - orphaned_doc_comment + - file_length + - type_name + - type_body_length + - multiple_closures_with_trailing_closure + - unused_optional_binding + + # Rules descriptions: https://realm.github.io/SwiftLint/rule-directory.html + diff --git a/Example/DApp/ Accounts/AccountsView.swift b/Example/DApp/ Accounts/AccountsView.swift index afd428a0b..4c544cf3f 100644 --- a/Example/DApp/ Accounts/AccountsView.swift +++ b/Example/DApp/ Accounts/AccountsView.swift @@ -7,14 +7,14 @@ final class AccountsView: UIView { tableView.register(UITableViewCell.self, forCellReuseIdentifier: "accountCell") return tableView }() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground addSubview(tableView) - + subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16), tableView.leadingAnchor.constraint(equalTo: leadingAnchor), @@ -22,7 +22,7 @@ final class AccountsView: UIView { tableView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor) ]) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/Example/DApp/ Accounts/AccountsViewController.swift b/Example/DApp/ Accounts/AccountsViewController.swift index 98a7434f7..151d5d794 100644 --- a/Example/DApp/ Accounts/AccountsViewController.swift +++ b/Example/DApp/ Accounts/AccountsViewController.swift @@ -7,33 +7,33 @@ struct AccountDetails { let account: String } -final class AccountsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { - +final class AccountsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { + let session: Session var accountsDetails: [AccountDetails] = [] - var onDisconnect: (()->())? - + var onDisconnect: (() -> Void)? + private let accountsView: AccountsView = { AccountsView() }() - + init(session: Session) { self.session = session super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func loadView() { view = accountsView } - + override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Accounts" - + navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Disconnect", style: .plain, @@ -48,7 +48,7 @@ final class AccountsViewController: UIViewController, UITableViewDataSource, UIT } } } - + @objc private func disconnect() { Task { @@ -59,15 +59,15 @@ final class AccountsViewController: UIViewController, UITableViewDataSource, UIT } } catch { print(error) - //show failure alert + // show failure alert } } } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { accountsDetails.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "accountCell", for: indexPath) let details = accountsDetails[indexPath.row] @@ -76,18 +76,18 @@ final class AccountsViewController: UIViewController, UITableViewDataSource, UIT cell.textLabel?.numberOfLines = 0 return cell } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { showAccountRequestScreen(accountsDetails[indexPath.row]) } - + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 70 } - + func showAccountRequestScreen(_ details: AccountDetails) { let vc = AccountRequestViewController(session: session, accountDetails: details) navigationController?.pushViewController(vc, animated: true) } - + } diff --git a/Example/DApp/AccountRequest/AccountRequestView.swift b/Example/DApp/AccountRequest/AccountRequestView.swift index 3f446422f..d7f2aab76 100644 --- a/Example/DApp/AccountRequest/AccountRequestView.swift +++ b/Example/DApp/AccountRequest/AccountRequestView.swift @@ -1,4 +1,3 @@ - import UIKit import Foundation @@ -10,7 +9,7 @@ class AccountRequestView: UIView { imageView.layer.cornerRadius = 32 return imageView }() - + let chainLabel: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 17.0, weight: .heavy) @@ -32,9 +31,9 @@ class AccountRequestView: UIView { stackView.alignment = .center return stackView }() - + let tableView = UITableView() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground @@ -45,21 +44,21 @@ class AccountRequestView: UIView { headerStackView.addArrangedSubview(chainLabel) headerStackView.addArrangedSubview(accountLabel) - + subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ iconView.topAnchor.constraint(equalTo: topAnchor, constant: 64), iconView.centerXAnchor.constraint(equalTo: centerXAnchor), - + headerStackView.topAnchor.constraint(equalTo: iconView.bottomAnchor, constant: 32), headerStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32), headerStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32), - + tableView.topAnchor.constraint(equalTo: headerStackView.bottomAnchor, constant: 0), tableView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0), tableView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0), - tableView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), + tableView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor) ]) } diff --git a/Example/DApp/AccountRequest/AccountRequestViewController.swift b/Example/DApp/AccountRequest/AccountRequestViewController.swift index 7e49245b9..bd9711469 100644 --- a/Example/DApp/AccountRequest/AccountRequestViewController.swift +++ b/Example/DApp/AccountRequest/AccountRequestViewController.swift @@ -1,11 +1,9 @@ - - import Foundation import UIKit import WalletConnectSign import WalletConnectUtils -class AccountRequestViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { +class AccountRequestViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private let session: Session private let chainId: String private let account: String @@ -13,22 +11,22 @@ class AccountRequestViewController: UIViewController, UITableViewDelegate, UITab private let accountRequestView = { AccountRequestView() }() - + init(session: Session, accountDetails: AccountDetails) { self.session = session self.chainId = accountDetails.chain self.account = accountDetails.account super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func loadView() { view = accountRequestView } - + override func viewDidLoad() { super.viewDidLoad() accountRequestView.tableView.delegate = self @@ -37,26 +35,25 @@ class AccountRequestViewController: UIViewController, UITableViewDelegate, UITab accountRequestView.chainLabel.text = chainId accountRequestView.accountLabel.text = account } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { methods.count } - + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return "Methods" } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "method_cell", for: indexPath) cell.textLabel?.text = methods[indexPath.row] return cell } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let method = methods[indexPath.row] let requestParams = getRequest(for: method) - - + let request = Request(topic: session.topic, method: method, params: requestParams, chainId: Blockchain(chainId)!) Task { do { @@ -66,18 +63,18 @@ class AccountRequestViewController: UIViewController, UITableViewDelegate, UITab } } catch { print(error) - //show failure alert + // show failure alert } } } - + private func presentConfirmationAlert() { let alert = UIAlertController(title: "Request Sent", message: nil, preferredStyle: .alert) let action = UIAlertAction(title: "OK", style: .cancel) alert.addAction(action) present(alert, animated: true) } - + private func getRequest(for method: String) -> AnyCodable { let account = session.namespaces.first!.value.accounts.first!.absoluteString if method == "eth_sendTransaction" { @@ -97,7 +94,7 @@ struct Transaction: Codable { let gasPrice, value, nonce: String } -fileprivate enum Stub { +private enum Stub { static let tx = [Transaction(from: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", to: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", diff --git a/Example/DApp/AppDelegate.swift b/Example/DApp/AppDelegate.swift index 4f9cfcf20..1bccf58bf 100644 --- a/Example/DApp/AppDelegate.swift +++ b/Example/DApp/AppDelegate.swift @@ -1,4 +1,3 @@ - import UIKit @main @@ -22,5 +21,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } diff --git a/Example/DApp/Connect/ConnectView.swift b/Example/DApp/Connect/ConnectView.swift index 37430db26..c1c075504 100644 --- a/Example/DApp/Connect/ConnectView.swift +++ b/Example/DApp/Connect/ConnectView.swift @@ -1,16 +1,15 @@ - import Foundation import UIKit final class ConnectView: UIView { let tableView = UITableView() - + let qrCodeView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .center return imageView }() - + let copyButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Copy", for: .normal) @@ -21,7 +20,7 @@ final class ConnectView: UIView { button.layer.cornerRadius = 8 return button }() - + let connectWalletButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Connect Wallet", for: .normal) @@ -31,7 +30,7 @@ final class ConnectView: UIView { button.layer.cornerRadius = 8 return button }() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground @@ -41,31 +40,30 @@ final class ConnectView: UIView { addSubview(tableView) tableView.register(UITableViewCell.self, forCellReuseIdentifier: "pairing_cell") subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), - qrCodeView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 50), qrCodeView.centerXAnchor.constraint(equalTo: centerXAnchor), qrCodeView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.6), qrCodeView.widthAnchor.constraint(equalTo: qrCodeView.heightAnchor), - + copyButton.topAnchor.constraint(equalTo: qrCodeView.bottomAnchor, constant: 16), copyButton.centerXAnchor.constraint(equalTo: centerXAnchor), copyButton.widthAnchor.constraint(equalTo: qrCodeView.widthAnchor), copyButton.heightAnchor.constraint(equalToConstant: 44), - + connectWalletButton.topAnchor.constraint(equalTo: copyButton.bottomAnchor, constant: 16), connectWalletButton.centerXAnchor.constraint(equalTo: centerXAnchor), connectWalletButton.widthAnchor.constraint(equalTo: copyButton.widthAnchor), - connectWalletButton.heightAnchor.constraint(equalToConstant: 44), + connectWalletButton.heightAnchor.constraint(equalToConstant: 44) ]) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/Example/DApp/Connect/ConnectViewController.swift b/Example/DApp/Connect/ConnectViewController.swift index b3fbd108d..810279f25 100644 --- a/Example/DApp/Connect/ConnectViewController.swift +++ b/Example/DApp/Connect/ConnectViewController.swift @@ -1,4 +1,3 @@ - import Foundation import UIKit import WalletConnectSign @@ -12,19 +11,19 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie self.uriString = uri super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private let connectView: ConnectView = { ConnectView() }() - + override func loadView() { view = connectView } - + override func viewDidLoad() { super.viewDidLoad() DispatchQueue.global().async { [unowned self] in @@ -42,13 +41,13 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie connectView.copyButton.isHidden = true setUpSegmentedControl() } - + func setUpSegmentedControl() { segmentedControl.selectedSegmentIndex = 0 self.navigationItem.titleView = segmentedControl segmentedControl.addTarget(self, action: #selector(segmentAction), for: .valueChanged) } - + @objc func segmentAction() { if segmentedControl.selectedSegmentIndex == 0 { connectView.tableView.isHidden = false @@ -56,12 +55,11 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie connectView.tableView.isHidden = true } } - + @objc func copyURI() { UIPasteboard.general.string = uriString } - - + private func generateQRCode(from string: String) -> UIImage? { let data = string.data(using: .ascii) if let filter = CIFilter(name: "CIQRCodeGenerator") { @@ -73,7 +71,7 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie } return nil } - + @objc func connectWithExampleWallet() { let url = URL(string: "https://walletconnect.com/wc?uri=\(uriString)")! DispatchQueue.main.async { @@ -82,7 +80,7 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie } } } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { activePairings.count } @@ -92,7 +90,7 @@ class ConnectViewController: UIViewController, UITableViewDataSource, UITableVie cell.textLabel?.text = activePairings[indexPath.row].peer?.name ?? "" return cell } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let pairingTopic = activePairings[indexPath.row].topic let blockchains: Set = [Blockchain("eip155:1")!, Blockchain("eip155:137")!] diff --git a/Example/DApp/ResponseViewController.swift b/Example/DApp/ResponseViewController.swift index 56afb5c3f..4f8d1c0b3 100644 --- a/Example/DApp/ResponseViewController.swift +++ b/Example/DApp/ResponseViewController.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectSign import UIKit @@ -8,20 +7,20 @@ class ResponseViewController: UIViewController { private let responseView = { ResponseView() }() - + init(response: Response) { self.response = response super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func loadView() { view = responseView } - + override func viewDidLoad() { super.viewDidLoad() let record = Sign.instance.getSessionRequestRecord(id: response.result.id)! @@ -35,13 +34,12 @@ class ResponseViewController: UIViewController { } responseView.dismissButton.addTarget(self, action: #selector(dismissSelf), for: .touchUpInside) } - + @objc func dismissSelf() { dismiss(animated: true, completion: nil) } } - final class ResponseView: UIView { let nameLabel: UILabel = { @@ -50,7 +48,7 @@ final class ResponseView: UIView { label.font = UIFont.systemFont(ofSize: 17.0, weight: .heavy) return label }() - + let descriptionLabel: UILabel = { let label = UILabel() label.font = UIFont.preferredFont(forTextStyle: .subheadline) @@ -59,7 +57,7 @@ final class ResponseView: UIView { label.textAlignment = .center return label }() - + let dismissButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Dismiss", for: .normal) @@ -77,24 +75,24 @@ final class ResponseView: UIView { stackView.alignment = .center return stackView }() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground - + addSubview(headerStackView) addSubview(dismissButton) headerStackView.addArrangedSubview(nameLabel) headerStackView.addArrangedSubview(descriptionLabel) - + subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ - + headerStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 32), headerStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32), headerStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32), - + dismissButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), dismissButton.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor, constant: 16), dismissButton.heightAnchor.constraint(equalToConstant: 44), @@ -106,4 +104,3 @@ final class ResponseView: UIView { fatalError("init(coder:) has not been implemented") } } - diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index 355d93839..cb602f2aa 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -1,4 +1,3 @@ - import UIKit import WalletConnectSign import Combine @@ -8,7 +7,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? private var publishers = [AnyCancellable]() - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -21,22 +19,21 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { url: "wallet.connect", icons: ["https://avatars.githubusercontent.com/u/37784886"]) Sign.configure(Sign.Config(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a")) - + if CommandLine.arguments.contains("-cleanInstall") { try? Sign.instance.cleanup() } - + Sign.instance.sessionDeletePublisher .receive(on: DispatchQueue.main) .sink { [unowned self] _ in showSelectChainScreen() }.store(in: &publishers) - + Sign.instance.sessionResponsePublisher.sink { [unowned self] response in presentResponse(for: response) }.store(in: &publishers) - if let session = Sign.instance.getSessions().first { showAccountsScreen(session) } else { @@ -54,7 +51,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window?.makeKeyAndVisible() } } - + func showAccountsScreen(_ session: Session) { DispatchQueue.main.async { [unowned self] in let vc = AccountsViewController(session: session) @@ -65,7 +62,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window?.makeKeyAndVisible() } } - + func presentResponse(for response: Response) { DispatchQueue.main.async { [unowned self] in let vc = UINavigationController(rootViewController: ResponseViewController(response: response)) @@ -73,4 +70,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } } - diff --git a/Example/DApp/SelectChain/SelectChainView.swift b/Example/DApp/SelectChain/SelectChainView.swift index 81891e15a..1e54ad348 100644 --- a/Example/DApp/SelectChain/SelectChainView.swift +++ b/Example/DApp/SelectChain/SelectChainView.swift @@ -1,8 +1,6 @@ - import Foundation import UIKit - class SelectChainView: UIView { let tableView: UITableView = { let tableView = UITableView(frame: .zero, style: .insetGrouped) @@ -18,7 +16,7 @@ class SelectChainView: UIView { button.layer.cornerRadius = 8 return button }() - + override init(frame: CGRect) { super.init(frame: frame) tableView.register(UITableViewCell.self, forCellReuseIdentifier: "chain_cell") @@ -27,22 +25,21 @@ class SelectChainView: UIView { addSubview(connectButton) subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16), tableView.leadingAnchor.constraint(equalTo: leadingAnchor), tableView.trailingAnchor.constraint(equalTo: trailingAnchor), tableView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), - + connectButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), connectButton.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor), connectButton.heightAnchor.constraint(equalToConstant: 44), - connectButton.widthAnchor.constraint(equalToConstant: 120), + connectButton.widthAnchor.constraint(equalToConstant: 120) ]) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } - diff --git a/Example/DApp/SelectChain/SelectChainViewController.swift b/Example/DApp/SelectChain/SelectChainViewController.swift index 7eef4fe15..bfe28634b 100644 --- a/Example/DApp/SelectChain/SelectChainViewController.swift +++ b/Example/DApp/SelectChain/SelectChainViewController.swift @@ -1,5 +1,3 @@ - - import Foundation import WalletConnectSign import UIKit @@ -17,7 +15,7 @@ class SelectChainViewController: UIViewController, UITableViewDataSource { private var publishers = [AnyCancellable]() let chains = [Chain(name: "Ethereum", id: "eip155:1"), Chain(name: "Polygon", id: "eip155:137")] - var onSessionSettled: ((Session)->())? + var onSessionSettled: ((Session) -> Void)? override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Available Chains" @@ -27,7 +25,7 @@ class SelectChainViewController: UIViewController, UITableViewDataSource { onSessionSettled?(session) }.store(in: &publishers) } - + override func loadView() { view = selectChainView } @@ -43,18 +41,18 @@ class SelectChainViewController: UIViewController, UITableViewDataSource { showConnectScreen(uriString: uri!) } } - + private func showConnectScreen(uriString: String) { DispatchQueue.main.async { [unowned self] in let vc = UINavigationController(rootViewController: ConnectViewController(uri: uriString)) present(vc, animated: true, completion: nil) } } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { chains.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "chain_cell", for: indexPath) let chain = chains[indexPath.row] diff --git a/Example/ExampleApp/Request/RequestView.swift b/Example/ExampleApp/Request/RequestView.swift index f1e5c7faa..d5722d14d 100644 --- a/Example/ExampleApp/Request/RequestView.swift +++ b/Example/ExampleApp/Request/RequestView.swift @@ -2,13 +2,13 @@ import UIKit import SwiftUI final class RequestView: UIView { - + let nameLabel: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 17.0, weight: .heavy) return label }() - + let descriptionLabel: UILabel = { let label = UILabel() label.font = UIFont.preferredFont(forTextStyle: .subheadline) @@ -17,7 +17,7 @@ final class RequestView: UIView { label.textAlignment = .center return label }() - + let approveButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Sign", for: .normal) @@ -27,7 +27,7 @@ final class RequestView: UIView { button.titleLabel?.font = UIFont.systemFont(ofSize: 17.0, weight: .semibold) return button }() - + let rejectButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Reject", for: .normal) @@ -37,7 +37,7 @@ final class RequestView: UIView { button.titleLabel?.font = UIFont.systemFont(ofSize: 17.0, weight: .semibold) return button }() - + let headerStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .vertical @@ -45,51 +45,51 @@ final class RequestView: UIView { stackView.alignment = .center return stackView }() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground - + addSubview(headerStackView) addSubview(approveButton) addSubview(rejectButton) headerStackView.addArrangedSubview(nameLabel) headerStackView.addArrangedSubview(descriptionLabel) - + subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ headerStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 32), headerStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32), headerStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32), - + approveButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), approveButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), approveButton.heightAnchor.constraint(equalToConstant: 44), - + rejectButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), rejectButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16), rejectButton.heightAnchor.constraint(equalToConstant: 44), - + approveButton.widthAnchor.constraint(equalTo: rejectButton.widthAnchor), - rejectButton.leadingAnchor.constraint(equalTo: approveButton.trailingAnchor, constant: 16), + rejectButton.leadingAnchor.constraint(equalTo: approveButton.trailingAnchor, constant: 16) ]) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } struct RequestView_Previews: PreviewProvider { - + static func makeRequestView() -> RequestView { let view = RequestView() view.nameLabel.text = "Example name" view.descriptionLabel.text = String.loremIpsum return view } - + static var previews: some View { makeRequestView().makePreview() } diff --git a/Example/ExampleApp/Request/RequestViewController.swift b/Example/ExampleApp/Request/RequestViewController.swift index 3269cead9..f05ab4b0a 100644 --- a/Example/ExampleApp/Request/RequestViewController.swift +++ b/Example/ExampleApp/Request/RequestViewController.swift @@ -1,12 +1,11 @@ - import Foundation import UIKit import WalletConnectSign import Web3 class RequestViewController: UIViewController { - var onSign: (()->())? - var onReject: (()->())? + var onSign: (() -> Void)? + var onReject: (() -> Void)? let sessionRequest: Request private let requestView = RequestView() @@ -14,11 +13,11 @@ class RequestViewController: UIViewController { self.sessionRequest = sessionRequest super.init(nibName: nil, bundle: nil) } - + override func loadView() { view = requestView } - + override func viewDidLoad() { super.viewDidLoad() requestView.approveButton.addTarget(self, action: #selector(signAction), for: .touchUpInside) @@ -26,7 +25,7 @@ class RequestViewController: UIViewController { requestView.nameLabel.text = sessionRequest.method requestView.descriptionLabel.text = getParamsDescription() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -36,13 +35,13 @@ class RequestViewController: UIViewController { onSign?() dismiss(animated: true) } - + @objc private func rejectAction() { onReject?() dismiss(animated: true) } - + private func getParamsDescription() -> String { let method = sessionRequest.method if method == "personal_sign" { diff --git a/Example/ExampleApp/SceneDelegate.swift b/Example/ExampleApp/SceneDelegate.swift index 850a0f810..0d6bebcf3 100644 --- a/Example/ExampleApp/SceneDelegate.swift +++ b/Example/ExampleApp/SceneDelegate.swift @@ -6,27 +6,27 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - + let metadata = AppMetadata( name: "Example Wallet", description: "wallet description", url: "example.wallet", icons: ["https://avatars.githubusercontent.com/u/37784886"]) Sign.configure(Sign.Config(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a")) - + if CommandLine.arguments.contains("-cleanInstall") { try? Sign.instance.cleanup() } - + guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) window?.rootViewController = UITabBarController.createExampleApp() window?.makeKeyAndVisible() } - + func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, - let incomingURL = userActivity.webpageURL else { + let incomingURL = userActivity.webpageURL else { return } let wcUri = incomingURL.absoluteString.deletingPrefix("https://walletconnect.com/wc?uri=") @@ -44,8 +44,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } extension UITabBarController { - - static func createExampleApp() -> UINavigationController { + + static func createExampleApp() -> UINavigationController { let responderController = UINavigationController(rootViewController: WalletViewController()) return responderController } diff --git a/Example/ExampleApp/SessionDetails/SessionDetailView.swift b/Example/ExampleApp/SessionDetails/SessionDetailView.swift index f3d45057e..a0bfe05ab 100644 --- a/Example/ExampleApp/SessionDetails/SessionDetailView.swift +++ b/Example/ExampleApp/SessionDetails/SessionDetailView.swift @@ -2,34 +2,34 @@ import SwiftUI import WalletConnectSign struct SessionDetailView: View { - + @ObservedObject var viewModel: SessionDetailViewModel - + var didPressSessionRequest: ((Request) -> Void)? - + var body: some View { List { Section { headerView() } - + ForEach(viewModel.chains, id: \.self) { chain in Section(header: header(chain: chain)) { if let namespace = viewModel.namespace(for: chain) { - + if namespace.accounts.isNotEmpty { accountSection(chain: chain, namespace: namespace) } - + if namespace.methods.isNotEmpty { methodsSection(chain: chain, namespace: namespace) } - + if namespace.events.isNotEmpty { methodsSection(chain: chain, namespace: namespace) } } } } - + if viewModel.requests.isNotEmpty { requestsSection() } @@ -39,7 +39,7 @@ struct SessionDetailView: View { } private extension SessionDetailView { - + func accountSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { Section(header: headerRow("Accounts")) { ForEach(namespace.accounts, id: \.self) { account in @@ -50,7 +50,7 @@ private extension SessionDetailView { }} } } - + func methodsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { Section(header: headerRow("Methods")) { ForEach(namespace.methods, id: \.self) { method in @@ -61,7 +61,7 @@ private extension SessionDetailView { }} } } - + func eventsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { Section(header: headerRow("Events")) { ForEach(namespace.events, id: \.self) { event in @@ -72,7 +72,7 @@ private extension SessionDetailView { }} } } - + func requestsSection() -> some View { Section(header: Text("Pending requests")) { ForEach(viewModel.requests, id: \.method) { request in @@ -82,7 +82,7 @@ private extension SessionDetailView { } } } - + func headerView() -> some View { VStack(spacing: 12.0) { AsyncImage(url: viewModel.peerIconURL) { image in @@ -95,17 +95,17 @@ private extension SessionDetailView { } .frame(width: 64, height: 64) .frame(maxWidth: .infinity) - + Text(viewModel.peerName) .font(.headline) - + VStack { Text(viewModel.peerDescription) Text(viewModel.peerURL) } .font(.footnote) .foregroundColor(.secondaryLabel) - + Button("Ping") { viewModel.ping() } @@ -120,18 +120,18 @@ private extension SessionDetailView { Button("OK", role: .cancel) { } } } - + func headerRow(_ text: String) -> some View { return Text(text) .font(.footnote) .foregroundColor(.secondaryLabel) } - + func plainRow(_ text: String) -> some View { return Text(text) .font(.body) } - + func header(chain: String) -> some View { HStack { Text(chain) diff --git a/Example/ExampleApp/SessionDetails/SessionDetailViewController.swift b/Example/ExampleApp/SessionDetails/SessionDetailViewController.swift index 6a5be6b57..7c07cca78 100644 --- a/Example/ExampleApp/SessionDetails/SessionDetailViewController.swift +++ b/Example/ExampleApp/SessionDetails/SessionDetailViewController.swift @@ -4,22 +4,22 @@ import WalletConnectSign import WalletConnectUtils final class SessionDetailViewController: UIHostingController { - + private let viewModel: SessionDetailViewModel - + init(session: Session, client: Sign) { self.viewModel = SessionDetailViewModel(session: session, client: client) super.init(rootView: SessionDetailView(viewModel: viewModel)) - + rootView.didPressSessionRequest = { [weak self] request in self?.showSessionRequest(request) } } - + func reload() { viewModel.objectWillChange.send() } - + private func showSessionRequest(_ request: Request) { let viewController = RequestViewController(request) viewController.onSign = { [unowned self] in @@ -34,7 +34,7 @@ final class SessionDetailViewController: UIHostingController } present(viewController, animated: true) } - + private func respondOnSign(request: Request, response: JSONRPCResponse) { print("[WALLET] Respond on Sign") Task { @@ -45,7 +45,7 @@ final class SessionDetailViewController: UIHostingController } } } - + private func respondOnReject(request: Request) { print("[WALLET] Respond on Reject") Task { diff --git a/Example/ExampleApp/SessionDetails/SessionDetailViewModel.swift b/Example/ExampleApp/SessionDetails/SessionDetailViewModel.swift index dae76d8af..36ee89a25 100644 --- a/Example/ExampleApp/SessionDetails/SessionDetailViewModel.swift +++ b/Example/ExampleApp/SessionDetails/SessionDetailViewModel.swift @@ -6,24 +6,24 @@ import WalletConnectSign final class SessionDetailViewModel: ObservableObject { private let session: Session private let client: Sign - + enum Fields { case accounts case methods case events case chain } - + @Published var namespaces: [String: SessionNamespace] @Published var pingSuccess: Bool = false @Published var pingFailed: Bool = false - + init(session: Session, client: Sign) { self.session = session self.client = client self.namespaces = session.namespaces } - + var peerName: String { session.peer.name } @@ -42,7 +42,7 @@ final class SessionDetailViewModel: ObservableObject { var requests: [Request] { client.getPendingRequests(topic: session.topic) } - + func remove(field: Fields, at indices: IndexSet = [], for chain: String) async { let backup = namespaces @@ -53,18 +53,17 @@ final class SessionDetailViewModel: ObservableObject { case .events: removeEvents(at: indices, chain: chain) case .chain: removeChain(chain) } - + try await client.update( topic: session.topic, namespaces: namespaces ) - } - catch { + } catch { namespaces = backup print("[RESPONDER] Namespaces update failed with: \(error.localizedDescription)") } } - + func ping() { client.ping(topic: session.topic) { result in switch result { @@ -75,14 +74,14 @@ final class SessionDetailViewModel: ObservableObject { } } } - + func namespace(for chain: String) -> SessionNamespaceViewModel? { namespaces[chain].map { SessionNamespaceViewModel(namespace: $0) } } } private extension SessionDetailViewModel { - + func removeAccounts(at offsets: IndexSet, chain: String) { guard let viewModel = namespace(for: chain) else { return } @@ -91,7 +90,7 @@ private extension SessionDetailViewModel { namespace: viewModel.namespace ) } - + func removeMethods(at offsets: IndexSet, chain: String) { guard let viewModel = namespace(for: chain) else { return } @@ -100,23 +99,23 @@ private extension SessionDetailViewModel { namespace: viewModel.namespace ) } - + func removeEvents(at offsets: IndexSet, chain: String) { guard let viewModel = namespace(for: chain) else { return } - + namespaces[chain] = SessionNamespace( events: Set(viewModel.events.removing(atOffsets: offsets)), namespace: viewModel.namespace ) } - + func removeChain(_ chain: String) { namespaces.removeValue(forKey: chain) } } private extension Array { - + func removing(atOffsets offsets: IndexSet) -> Self { var array = self array.remove(atOffsets: offsets) @@ -125,7 +124,7 @@ private extension Array { } private extension SessionNamespace { - + init( accounts: Set? = nil, methods: Set? = nil, diff --git a/Example/ExampleApp/SessionDetails/SessionDetailsViewController.swift b/Example/ExampleApp/SessionDetails/SessionDetailsViewController.swift index d0d6a6753..f53ecbdef 100644 --- a/Example/ExampleApp/SessionDetails/SessionDetailsViewController.swift +++ b/Example/ExampleApp/SessionDetails/SessionDetailsViewController.swift @@ -9,8 +9,8 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, private var sessionInfo: SessionInfo private let session: Session init(_ session: Session) { - let pendingRequests = Sign.instance.getPendingRequests(topic: session.topic).map{$0.method} - let chains = Array(session.namespaces.values.flatMap { n in n.accounts.map{$0.blockchain.absoluteString}}) + let pendingRequests = Sign.instance.getPendingRequests(topic: session.topic).map {$0.method} + let chains = Array(session.namespaces.values.flatMap { n in n.accounts.map {$0.blockchain.absoluteString}}) let methods = Array(session.namespaces.values.first?.methods ?? []) // TODO: Rethink how to show this info on example app self.sessionInfo = SessionInfo(name: session.peer.name, descriptionText: session.peer.description, @@ -22,11 +22,11 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, self.session = session super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { show(sessionInfo) super.viewDidLoad() @@ -35,7 +35,7 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, sessiondetailsView.tableView.dataSource = self sessiondetailsView.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") } - + override func loadView() { view = sessiondetailsView } @@ -46,21 +46,21 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, sessiondetailsView.urlLabel.text = sessionInfo.dappURL sessiondetailsView.loadImage(at: sessionInfo.iconURL) } - + @objc private func ping() { Sign.instance.ping(topic: session.topic) { result in switch result { - case .success(): + case .success: print("received ping response") case .failure(let error): print(error) } } } - - //MARK: - Table View - + + // MARK: - Table View + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return sessionInfo.chains.count @@ -70,7 +70,7 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, return sessionInfo.pendingRequests.count } } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) if indexPath.section == 0 { @@ -82,11 +82,11 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, } return cell } - + func numberOfSections(in tableView: UITableView) -> Int { return 3 } - + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { if section == 0 { return "Chains" @@ -96,14 +96,14 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, return "Pending Requests" } } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if indexPath.section == 2 { let pendingRequests = Sign.instance.getPendingRequests(topic: session.topic) showSessionRequest(pendingRequests[indexPath.row]) } } - + private func showSessionRequest(_ sessionRequest: Request) { let requestVC = RequestViewController(sessionRequest) requestVC.onSign = { [unowned self] in @@ -118,10 +118,10 @@ final class SessionDetailsViewController: UIViewController, UITableViewDelegate, } present(requestVC, animated: true) } - + func reloadTable() { - let pendingRequests = Sign.instance.getPendingRequests(topic: session.topic).map{$0.method} - let chains = Array(session.namespaces.values.flatMap { n in n.accounts.map{$0.blockchain.absoluteString}}) + let pendingRequests = Sign.instance.getPendingRequests(topic: session.topic).map {$0.method} + let chains = Array(session.namespaces.values.flatMap { n in n.accounts.map {$0.blockchain.absoluteString}}) let methods = Array(session.namespaces.values.first?.methods ?? []) // TODO: Rethink how to show this info on example app self.sessionInfo = SessionInfo(name: session.peer.name, descriptionText: session.peer.description, diff --git a/Example/ExampleApp/SessionDetails/SessionNamespaceViewModel.swift b/Example/ExampleApp/SessionDetails/SessionNamespaceViewModel.swift index 2a732a377..2db857a29 100644 --- a/Example/ExampleApp/SessionDetails/SessionNamespaceViewModel.swift +++ b/Example/ExampleApp/SessionDetails/SessionNamespaceViewModel.swift @@ -3,7 +3,7 @@ import WalletConnectSign struct SessionNamespaceViewModel { let namespace: SessionNamespace - + var accounts: [Account] { namespace.accounts.sorted(by: { $0.absoluteString < $1.absoluteString diff --git a/Example/ExampleApp/SessionProposal/Proposal.swift b/Example/ExampleApp/SessionProposal/Proposal.swift index 9abe02068..7e37e1500 100644 --- a/Example/ExampleApp/SessionProposal/Proposal.swift +++ b/Example/ExampleApp/SessionProposal/Proposal.swift @@ -6,13 +6,13 @@ struct Proposal { let proposerURL: String let iconURL: String let permissions: [Namespace] - + struct Namespace: Hashable { let chains: [String] let methods: [String] let events: [String] } - + internal init(proposal: Session.Proposal) { self.proposerName = proposal.proposer.name self.proposerDescription = proposal.proposer.description @@ -24,7 +24,7 @@ struct Proposal { methods: ["eth_sendTransaction", "personal_sign", "eth_signTypedData"], events: ["accountsChanged", "chainChanged"])] } - + internal init(proposerName: String, proposerDescription: String, proposerURL: String, iconURL: String, permissions: [Proposal.Namespace]) { self.proposerName = proposerName self.proposerDescription = proposerDescription @@ -32,7 +32,7 @@ struct Proposal { self.iconURL = iconURL self.permissions = permissions } - + static func mock() -> Proposal { Proposal( proposerName: "Example name", diff --git a/Example/ExampleApp/SessionProposal/ProposalView.swift b/Example/ExampleApp/SessionProposal/ProposalView.swift index cdb1fea9b..cf7052bba 100644 --- a/Example/ExampleApp/SessionProposal/ProposalView.swift +++ b/Example/ExampleApp/SessionProposal/ProposalView.swift @@ -1,12 +1,12 @@ import SwiftUI struct ProposalView: View { - + var didPressApprove: (() -> Void)? var didPressReject: (() -> Void)? - + let proposal: Proposal - + var body: some View { VStack { headerView @@ -18,7 +18,7 @@ struct ProposalView: View { .padding(16) } } - + func asyncImage(urlString: String) -> some View { AsyncImage(url: URL(string: urlString)) { phase in if case .success(let image) = phase { @@ -28,7 +28,7 @@ struct ProposalView: View { } } } - + // App metadata for the session var headerView: some View { VStack(alignment: .center, spacing: 12) { @@ -49,7 +49,7 @@ struct ProposalView: View { .fixedSize(horizontal: false, vertical: true) } } - + // Scrollable view with permissions text var permissionsView: some View { VStack(alignment: .leading, spacing: 8) { @@ -72,7 +72,7 @@ struct ProposalView: View { .background(Color.secondarySystemBackground) } } - + // Displays a chain's methods and events func sectionView(for namespace: Proposal.Namespace) -> some View { VStack(alignment: .leading, spacing: 6) { @@ -104,7 +104,7 @@ struct ProposalView: View { } } } - + // Approve and reject buttons var footerView: some View { HStack { @@ -119,7 +119,7 @@ struct ProposalView: View { } .background(Color.blue) .cornerRadius(8) - + Button { didPressReject?() } label: { @@ -136,7 +136,7 @@ struct ProposalView: View { } struct ProposalView_Previews: PreviewProvider { - + static var previews: some View { ProposalView(proposal: Proposal.mock()) ProposalView(proposal: Proposal.mock()).preferredColorScheme(.dark) diff --git a/Example/ExampleApp/SessionProposal/ProposalViewController.swift b/Example/ExampleApp/SessionProposal/ProposalViewController.swift index fdd4c5236..115213d5b 100644 --- a/Example/ExampleApp/SessionProposal/ProposalViewController.swift +++ b/Example/ExampleApp/SessionProposal/ProposalViewController.swift @@ -7,9 +7,9 @@ protocol ProposalViewControllerDelegate: AnyObject { } final class ProposalViewController: UIHostingController { - + weak var delegate: ProposalViewControllerDelegate? - + init(proposal: Proposal) { super.init(rootView: ProposalView(proposal: proposal)) rootView.didPressApprove = { [weak self] in @@ -19,17 +19,17 @@ final class ProposalViewController: UIHostingController { self?.rejectSession() } } - + private func approveSession() { delegate?.didApproveSession() dismiss(animated: true) } - + private func rejectSession() { delegate?.didRejectSession() dismiss(animated: true) } - + @MainActor required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/Example/ExampleApp/Shared/Array.swift b/Example/ExampleApp/Shared/Array.swift index f9d4fbca1..7314d8c65 100644 --- a/Example/ExampleApp/Shared/Array.swift +++ b/Example/ExampleApp/Shared/Array.swift @@ -1,7 +1,7 @@ import Foundation extension Array { - + var isNotEmpty: Bool { return !isEmpty } diff --git a/Example/ExampleApp/Shared/Color+Extension.swift b/Example/ExampleApp/Shared/Color+Extension.swift index 13657b08e..c18e75f25 100644 --- a/Example/ExampleApp/Shared/Color+Extension.swift +++ b/Example/ExampleApp/Shared/Color+Extension.swift @@ -1,15 +1,15 @@ import SwiftUI extension Color { - + static var secondaryLabel: Color { Color(uiColor: .secondaryLabel) } - + static var tertiaryLabel: Color { Color(uiColor: .tertiaryLabel) } - + static var secondarySystemBackground: Color { Color(uiColor: .secondarySystemBackground) } diff --git a/Example/ExampleApp/Shared/EthereumTransaction.swift b/Example/ExampleApp/Shared/EthereumTransaction.swift index e6433ea98..ac167fc9f 100644 --- a/Example/ExampleApp/Shared/EthereumTransaction.swift +++ b/Example/ExampleApp/Shared/EthereumTransaction.swift @@ -1,4 +1,3 @@ - import Foundation import Web3 diff --git a/Example/ExampleApp/Shared/Signer.swift b/Example/ExampleApp/Shared/Signer.swift index 5ec467c85..d1f2a9fc6 100644 --- a/Example/ExampleApp/Shared/Signer.swift +++ b/Example/ExampleApp/Shared/Signer.swift @@ -5,7 +5,7 @@ import WalletConnectSign class Signer { static let privateKey: EthereumPrivateKey = try! EthereumPrivateKey(hexPrivateKey: "0xe56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") - private init(){} + private init() {} static func signEth(request: Request) -> AnyCodable { let method = request.method if method == "personal_sign" { @@ -16,7 +16,7 @@ class Signer { let result = "0x" + r.toHexString() + s.toHexString() + String(v + 27, radix: 16) return AnyCodable(result) } else if method == "eth_signTypedData" { - //TODO + // TODO let result = "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" return AnyCodable(result) } else if method == "eth_sendTransaction" { @@ -31,7 +31,7 @@ class Signer { } fatalError("not implemented") } - + private static func dataToHash(_ message: String) -> Bytes { let prefix = "\u{19}Ethereum Signed Message:\n" let messageData = Data(hex: message) diff --git a/Example/ExampleApp/Shared/UIAlertController.swift b/Example/ExampleApp/Shared/UIAlertController.swift index eaa509c10..d24ea4abb 100644 --- a/Example/ExampleApp/Shared/UIAlertController.swift +++ b/Example/ExampleApp/Shared/UIAlertController.swift @@ -1,7 +1,7 @@ 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 connect: () -> Void = { diff --git a/Example/ExampleApp/Shared/UIKit+Previews.swift b/Example/ExampleApp/Shared/UIKit+Previews.swift index d95ae8402..9a005115a 100644 --- a/Example/ExampleApp/Shared/UIKit+Previews.swift +++ b/Example/ExampleApp/Shared/UIKit+Previews.swift @@ -1,13 +1,13 @@ import SwiftUI public extension UIView { - + struct Preview: UIViewRepresentable { let view: UIView public func makeUIView(context: Context) -> some UIView { view } public func updateUIView(_ uiView: UIViewType, context: Context) {} } - + func makePreview() -> some View { Preview(view: self) } diff --git a/Example/ExampleApp/Shared/Utilities.swift b/Example/ExampleApp/Shared/Utilities.swift index da4f9cc4c..b888dedcf 100644 --- a/Example/ExampleApp/Shared/Utilities.swift +++ b/Example/ExampleApp/Shared/Utilities.swift @@ -1,5 +1,5 @@ extension String { - + static var loremIpsum: String { "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." } diff --git a/Example/ExampleApp/Wallet/ActiveSessionCell.swift b/Example/ExampleApp/Wallet/ActiveSessionCell.swift index a349fdcbe..e08d5ba8a 100644 --- a/Example/ExampleApp/Wallet/ActiveSessionCell.swift +++ b/Example/ExampleApp/Wallet/ActiveSessionCell.swift @@ -1,7 +1,7 @@ import UIKit final class ActiveSessionCell: UITableViewCell { - + var item: ActiveSessionItem? { didSet { if let item = item { @@ -9,55 +9,55 @@ final class ActiveSessionCell: UITableViewCell { } } } - + private let iconView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit imageView.layer.cornerRadius = 20 return imageView }() - + private let titleLabel: UILabel = { let label = UILabel() label.setContentHuggingPriority(.defaultHigh, for: .vertical) return label }() - + private let subtitleLabel: UILabel = { let label = UILabel() label.font = UIFont.preferredFont(forTextStyle: .caption1) label.textColor = .secondaryLabel return label }() - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) accessoryType = .disclosureIndicator selectionStyle = .none - + contentView.addSubview(iconView) contentView.addSubview(titleLabel) contentView.addSubview(subtitleLabel) - + contentView.subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ iconView.heightAnchor.constraint(equalToConstant: 40), iconView.heightAnchor.constraint(equalTo: iconView.widthAnchor), iconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), iconView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), titleLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 16), titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16), - + subtitleLabel.topAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor, constant: 6), subtitleLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor), subtitleLabel.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor), subtitleLabel.lastBaselineAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12) ]) } - + private func show(_ item: ActiveSessionItem) { titleLabel.text = item.dappName subtitleLabel.text = item.dappURL @@ -71,7 +71,7 @@ final class ActiveSessionCell: UITableViewCell { } } } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/Example/ExampleApp/Wallet/ScannerViewController.swift b/Example/ExampleApp/Wallet/ScannerViewController.swift index b962a3708..999fb48c3 100644 --- a/Example/ExampleApp/Wallet/ScannerViewController.swift +++ b/Example/ExampleApp/Wallet/ScannerViewController.swift @@ -6,15 +6,15 @@ protocol ScannerViewControllerDelegate: AnyObject { } final class ScannerViewController: UIViewController { - + weak var delegate: ScannerViewControllerDelegate? - + private let captureSession = AVCaptureSession() - + override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .black - + guard let captureDevice = AVCaptureDevice.default(for: .video) else { return } @@ -26,7 +26,7 @@ final class ScannerViewController: UIViewController { print("Error on capture setup: \(error)") } } - + private func startCaptureSession(with input: AVCaptureDeviceInput) { captureSession.addInput(input) let metadataOutput = AVCaptureMetadataOutput() @@ -35,7 +35,7 @@ final class ScannerViewController: UIViewController { metadataOutput.metadataObjectTypes = [.qr] captureSession.startRunning() } - + private func startVideoPreview() { let videoLayer = AVCaptureVideoPreviewLayer(session: captureSession) videoLayer.videoGravity = .resizeAspectFill @@ -45,17 +45,17 @@ final class ScannerViewController: UIViewController { } extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate { - + func metadataOutput( _ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { - + if let metadata = metadataObjects.first as? AVMetadataMachineReadableCodeObject, metadata.type == .qr, let qrCode = metadata.stringValue { captureSession.stopRunning() - dismiss(animated: true) { [weak self] in + dismiss(animated: true) { [weak self] in self?.delegate?.didScan(qrCode) } } diff --git a/Example/ExampleApp/Wallet/WalletView.swift b/Example/ExampleApp/Wallet/WalletView.swift index bb82685e7..e0bc6cdb8 100644 --- a/Example/ExampleApp/Wallet/WalletView.swift +++ b/Example/ExampleApp/Wallet/WalletView.swift @@ -2,13 +2,13 @@ import UIKit import SwiftUI final class WalletView: UIView { - + let tableView: UITableView = { let tableView = UITableView(frame: .zero, style: .insetGrouped) tableView.register(ActiveSessionCell.self, forCellReuseIdentifier: "sessionCell") return tableView }() - + let scanButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Scan QR code", for: .normal) @@ -18,7 +18,7 @@ final class WalletView: UIView { button.layer.cornerRadius = 8 return button }() - + let pasteButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Paste URI", for: .normal) @@ -28,43 +28,43 @@ final class WalletView: UIView { button.layer.cornerRadius = 8 return button }() - + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemBackground - + addSubview(tableView) addSubview(pasteButton) addSubview(scanButton) - + subviews.forEach { $0.translatesAutoresizingMaskIntoConstraints = false } - + NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: leadingAnchor), tableView.trailingAnchor.constraint(equalTo: trailingAnchor), tableView.bottomAnchor.constraint(equalTo: scanButton.topAnchor), - + pasteButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), pasteButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), pasteButton.heightAnchor.constraint(equalToConstant: 44), - + scanButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16), scanButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16), scanButton.heightAnchor.constraint(equalToConstant: 44), - + pasteButton.widthAnchor.constraint(equalTo: scanButton.widthAnchor), scanButton.leadingAnchor.constraint(equalTo: pasteButton.trailingAnchor, constant: 16) ]) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } struct WalletView_Previews: PreviewProvider { - + static var previews: some View { WalletView().makePreview() WalletView().makePreview().preferredColorScheme(.dark) diff --git a/Example/ExampleApp/Wallet/WalletViewController.swift b/Example/ExampleApp/Wallet/WalletViewController.swift index eb27e02a4..13f088125 100644 --- a/Example/ExampleApp/Wallet/WalletViewController.swift +++ b/Example/ExampleApp/Wallet/WalletViewController.swift @@ -9,37 +9,37 @@ final class WalletViewController: UIViewController { lazy var account = Signer.privateKey.address.hex(eip55: true) var sessionItems: [ActiveSessionItem] = [] var currentProposal: Session.Proposal? - var onClientConnected: (()->())? + var onClientConnected: (() -> Void)? private var publishers = [AnyCancellable]() private let walletView: WalletView = { WalletView() }() - + override func loadView() { view = walletView } - + override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Wallet" walletView.scanButton.addTarget(self, action: #selector(showScanner), for: .touchUpInside) walletView.pasteButton.addTarget(self, action: #selector(showTextInput), for: .touchUpInside) - + walletView.tableView.dataSource = self walletView.tableView.delegate = self let settledSessions = Sign.instance.getSessions() sessionItems = getActiveSessionItem(for: settledSessions) setUpAuthSubscribing() } - + @objc private func showScanner() { let scannerViewController = ScannerViewController() scannerViewController.delegate = self present(scannerViewController, animated: true) } - + @objc private func showTextInput() { let alert = UIAlertController.createInputAlert { [weak self] inputText in @@ -47,7 +47,7 @@ final class WalletViewController: UIViewController { } present(alert, animated: true) } - + private func showSessionProposal(_ proposal: Proposal) { let proposalViewController = ProposalViewController(proposal: proposal) proposalViewController.delegate = self @@ -58,7 +58,7 @@ final class WalletViewController: UIViewController { let viewController = SessionDetailViewController(session: session, client: Sign.instance) navigationController?.present(viewController, animated: true) } - + private func showSessionRequest(_ request: Request) { let requestVC = RequestViewController(request) requestVC.onSign = { [unowned self] in @@ -74,7 +74,7 @@ final class WalletViewController: UIViewController { reloadSessionDetailsIfNeeded() present(requestVC, animated: true) } - + func reloadSessionDetailsIfNeeded() { if let viewController = navigationController?.presentedViewController as? SessionDetailViewController { viewController.reload() @@ -124,7 +124,7 @@ final class WalletViewController: UIViewController { } @MainActor - private func approve(proposalId: String, namespaces: [String : SessionNamespace]) { + private func approve(proposalId: String, namespaces: [String: SessionNamespace]) { print("[WALLET] Approve Session: \(proposalId)") Task { do { @@ -149,11 +149,11 @@ final class WalletViewController: UIViewController { } extension WalletViewController: UITableViewDataSource, UITableViewDelegate { - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { sessionItems.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "sessionCell", for: indexPath) as! ActiveSessionCell cell.item = sessionItems[indexPath.row] @@ -177,11 +177,11 @@ extension WalletViewController: UITableViewDataSource, UITableViewDelegate { } } } - + func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? { "Disconnect" } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("did select row \(indexPath)") let itemTopic = sessionItems[indexPath.row].topic @@ -192,14 +192,14 @@ extension WalletViewController: UITableViewDataSource, UITableViewDelegate { } extension WalletViewController: ScannerViewControllerDelegate { - + func didScan(_ code: String) { pairClient(uri: code) } } extension WalletViewController: ProposalViewControllerDelegate { - + func didApproveSession() { let proposal = currentProposal! currentProposal = nil @@ -207,10 +207,10 @@ extension WalletViewController: ProposalViewControllerDelegate { proposal.requiredNamespaces.forEach { let caip2Namespace = $0.key let proposalNamespace = $0.value - let accounts = Set(proposalNamespace.chains.compactMap { Account($0.absoluteString + ":\(account)") } ) - + let accounts = Set(proposalNamespace.chains.compactMap { Account($0.absoluteString + ":\(account)") }) + let extensions: [SessionNamespace.Extension]? = proposalNamespace.extensions?.map { element in - let accounts = Set(element.chains.compactMap { Account($0.absoluteString + ":\(account)") } ) + let accounts = Set(element.chains.compactMap { Account($0.absoluteString + ":\(account)") }) return SessionNamespace.Extension(accounts: accounts, methods: element.methods, events: element.events) } let sessionNamespace = SessionNamespace(accounts: accounts, methods: proposalNamespace.methods, events: proposalNamespace.events, extensions: extensions) @@ -218,7 +218,7 @@ extension WalletViewController: ProposalViewControllerDelegate { } approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - + func didRejectSession() { let proposal = currentProposal! currentProposal = nil @@ -261,7 +261,7 @@ extension WalletViewController { Sign.instance.sessionDeletePublisher .receive(on: DispatchQueue.main) - .sink { [weak self] sessionRequest in + .sink { [weak self] _ in self?.reloadActiveSessions() self?.navigationController?.popToRootViewController(animated: true) }.store(in: &publishers) diff --git a/Example/UITests/Engine/App.swift b/Example/UITests/Engine/App.swift index e4dba88df..1da588e56 100644 --- a/Example/UITests/Engine/App.swift +++ b/Example/UITests/Engine/App.swift @@ -6,7 +6,7 @@ enum App { case wallet case safari case springboard - + var bundleID: String { switch self { case .dapp: @@ -19,7 +19,7 @@ enum App { return "com.apple.springboard" } } - + var displayName: String { switch self { case .dapp: @@ -32,7 +32,7 @@ enum App { fatalError() } } - + var instance: XCUIApplication { return XCUIApplication(bundleIdentifier: bundleID) } diff --git a/Example/UITests/Engine/DAppEngine.swift b/Example/UITests/Engine/DAppEngine.swift index 80c1e3f25..62228fe4a 100644 --- a/Example/UITests/Engine/DAppEngine.swift +++ b/Example/UITests/Engine/DAppEngine.swift @@ -2,37 +2,37 @@ import Foundation import XCTest struct DAppEngine { - + private var instance: XCUIApplication { return App.dapp.instance } - + // Main screen - + var connectButton: XCUIElement { instance.buttons["Connect"] } - + // Accounts screen - + var accountRow: XCUIElement { instance.staticTexts["0xe5EeF1368781911d265fDB6946613dA61915a501"] } - + var disconnectButton: XCUIElement { instance.buttons["Disconnect"] } - + // Pairing screen - + var pairingRow: XCUIElement { instance.staticTexts["Example Wallet"] } - + var newPairingButton: XCUIElement { instance.buttons["New Pairing"] } - + var copyURIButton: XCUIElement { instance.buttons["Copy"] } diff --git a/Example/UITests/Engine/Engine.swift b/Example/UITests/Engine/Engine.swift index f945aa3d7..6e1b9acf6 100644 --- a/Example/UITests/Engine/Engine.swift +++ b/Example/UITests/Engine/Engine.swift @@ -6,7 +6,7 @@ struct Engine { let dapp = DAppEngine() let wallet = WalletEngine() let safari = SafariEngine() - + /// Approve session request /// - Context: /// - wallet opened diff --git a/Example/UITests/Engine/RoutingEngine.swift b/Example/UITests/Engine/RoutingEngine.swift index 5d891c1c3..9a0c46640 100644 --- a/Example/UITests/Engine/RoutingEngine.swift +++ b/Example/UITests/Engine/RoutingEngine.swift @@ -2,7 +2,7 @@ import Foundation import XCTest struct RoutingEngine { - + private var springboard: XCUIApplication { return App.springboard.instance } @@ -19,17 +19,17 @@ struct RoutingEngine { app.launch() } } - + func activate(app: App) { let app = app.instance app.activate() app.waitForAppearence() } - + func home() { XCUIDevice.shared.press(.home) } - + func wait(for interval: TimeInterval) { Thread.sleep(forTimeInterval: interval) } diff --git a/Example/UITests/Engine/SafariEngine.swift b/Example/UITests/Engine/SafariEngine.swift index 657dcfbaa..69a2d5bc5 100644 --- a/Example/UITests/Engine/SafariEngine.swift +++ b/Example/UITests/Engine/SafariEngine.swift @@ -2,7 +2,7 @@ import Foundation import XCTest struct SafariEngine { - + private var instance: XCUIApplication { return App.safari.instance } diff --git a/Example/UITests/Engine/WalletEngine.swift b/Example/UITests/Engine/WalletEngine.swift index aac67006f..536e45443 100644 --- a/Example/UITests/Engine/WalletEngine.swift +++ b/Example/UITests/Engine/WalletEngine.swift @@ -2,25 +2,25 @@ import Foundation import XCTest struct WalletEngine { - + private var instance: XCUIApplication { return App.wallet.instance } - + // MainScreen - + var pasteURIButton: XCUIElement { instance.buttons["Paste URI"] } - + var alert: XCUIElement { instance.alerts["Paste URI"] } - + var uriTextfield: XCUIElement { alert.textFields.firstMatch } - + var pasteAndConnect: XCUIElement { alert.buttons["Paste and Connect"] } @@ -30,21 +30,21 @@ struct WalletEngine { } // Proposal - + var approveButton: XCUIElement { instance.buttons["Approve"] } - + var rejectButton: XCUIElement { instance.buttons["Reject"] } - + // SessionDetails - + var pingButton: XCUIElement { instance.buttons["Ping"] } - + var pingAlert: XCUIElement { instance.alerts.element.staticTexts["Received ping response"] } diff --git a/Example/UITests/Extensions/XCUIElement.swift b/Example/UITests/Extensions/XCUIElement.swift index 2e11ea9ca..d9ddc5c12 100644 --- a/Example/UITests/Extensions/XCUIElement.swift +++ b/Example/UITests/Extensions/XCUIElement.swift @@ -7,17 +7,17 @@ extension XCUIElement { func waitForAppearence(timeout: TimeInterval = 5) -> Bool { return waitForExistence(timeout: timeout) } - + func waitTap() { waitForAppearence() tap() } - + func waitTypeText(_ text: String) { waitForAppearence() typeText(text) } - + func waitExists() -> Bool { waitForAppearence() return exists diff --git a/Example/UITests/Regression/RegressionTests.swift b/Example/UITests/Regression/RegressionTests.swift index 3157b6739..716ba8702 100644 --- a/Example/UITests/Regression/RegressionTests.swift +++ b/Example/UITests/Regression/RegressionTests.swift @@ -1,15 +1,15 @@ import XCTest class PairingTests: XCTestCase { - + private let engine: Engine = Engine() - + private static var cleanLaunch: Bool = true override func setUp() { engine.routing.launch(app: .dapp, clean: PairingTests.cleanLaunch) engine.routing.launch(app: .wallet, clean: PairingTests.cleanLaunch) - + PairingTests.cleanLaunch = false } @@ -35,18 +35,18 @@ class PairingTests: XCTestCase { engine.approveSessionAndCheck() } - + /// Check session ping on Wallet /// - TU002 func test02PingResponse() { engine.routing.activate(app: .wallet) - + engine.wallet.sessionRow.waitTap() engine.wallet.pingButton.waitTap() - + XCTAssertTrue(engine.wallet.pingAlert.waitExists()) } - + /// Approve session on existing pairing /// - TU004 func test04ApproveSessionExistingPairing() { @@ -55,10 +55,10 @@ class PairingTests: XCTestCase { engine.dapp.disconnectButton.waitTap() engine.dapp.connectButton.waitTap() engine.dapp.pairingRow.waitTap() - + // TODO: Figure out why you need to wait here engine.routing.wait(for: 2) - + engine.approveSessionAndCheck() } } diff --git a/Package.swift b/Package.swift index ee807b8e4..bfe275282 100644 --- a/Package.swift +++ b/Package.swift @@ -7,15 +7,15 @@ let package = Package( platforms: [ .iOS(.v13), .macOS(.v10_15), - .tvOS(.v13), + .tvOS(.v13) ], products: [ .library( name: "WalletConnect", - targets: ["WalletConnectSign"]), + targets: ["WalletConnectSign"]) ], dependencies: [ - .package(url: "https://github.com/daltoniam/Starscream.git", .upToNextMajor(from: "3.0.0")), + .package(url: "https://github.com/daltoniam/Starscream.git", .upToNextMajor(from: "3.0.0")) ], targets: [ .target( @@ -70,7 +70,7 @@ let package = Package( dependencies: ["JSONRPC", "TestingUtils"]), .testTarget( name: "CommonsTests", - dependencies: ["Commons", "TestingUtils"]), + dependencies: ["Commons", "TestingUtils"]) ], swiftLanguageVersions: [.v5] ) diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index 01b5b42e7..fe54d4efb 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -1,25 +1,23 @@ - import Foundation import WalletConnectUtils import WalletConnectKMS import WalletConnectRelay import Combine - class Chat { private var publishers = [AnyCancellable]() let registry: Registry let registryManager: RegistryManager let engine: Engine let kms: KeyManagementService - + let socketConnectionStatusPublisher: AnyPublisher - + var newThreadPublisherSubject = PassthroughSubject() public var newThreadPublisher: AnyPublisher { newThreadPublisherSubject.eraseToAnyPublisher() } - + var invitePublisherSubject = PassthroughSubject() public var invitePublisher: AnyPublisher { invitePublisherSubject.eraseToAnyPublisher() @@ -47,7 +45,7 @@ class Chat { socketConnectionStatusPublisher = relayClient.socketConnectionStatusPublisher setUpEnginesCallbacks() } - + /// Registers a new record on Chat keyserver, /// record is a blockchain account with a client generated public key /// - Parameter account: CAIP10 blockchain account @@ -55,14 +53,14 @@ class Chat { func register(account: Account) async throws -> String { try await registryManager.register(account: account) } - + /// Queries the default keyserver with a blockchain account /// - Parameter account: CAIP10 blockachain account /// - Returns: public key associated with an account in chat's keyserver func resolve(account: Account) async throws -> String { try await registry.resolve(account: account) } - + /// Sends a chat invite with opening message /// - Parameters: /// - publicKey: publicKey associated with a peer @@ -70,25 +68,25 @@ class Chat { func invite(publicKey: String, openingMessage: String) async throws { try await engine.invite(peerPubKey: publicKey, openingMessage: openingMessage) } - + func accept(inviteId: String) async throws { try await engine.accept(inviteId: inviteId) } - + /// Sends a chat message to an active chat thread /// - Parameters: /// - topic: thread topic /// - message: chat message func message(topic: String, message: String) { - + } - + /// To Ping peer client /// - Parameter topic: chat thread topic func ping(topic: String) { - + } - + private func setUpEnginesCallbacks() { engine.onInvite = { [unowned self] invite in invitePublisherSubject.send(invite) @@ -98,4 +96,3 @@ class Chat { } } } - diff --git a/Sources/Chat/Engine.swift b/Sources/Chat/Engine.swift index eaff34169..8a187e0f5 100644 --- a/Sources/Chat/Engine.swift +++ b/Sources/Chat/Engine.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectKMS import WalletConnectUtils @@ -6,8 +5,8 @@ import WalletConnectRelay import Combine class Engine { - var onInvite: ((Invite)->())? - var onNewThread: ((Thread)->())? + var onInvite: ((Invite) -> Void)? + var onNewThread: ((Thread) -> Void)? let networkingInteractor: NetworkingInteractor let inviteStore: CodableStore<(Invite)> let topicToInvitationPubKeyStore: CodableStore @@ -16,7 +15,7 @@ class Engine { let kms: KeyManagementService let threadsStore: CodableStore private var publishers = [AnyCancellable]() - + init(registry: Registry, networkingInteractor: NetworkingInteractor, kms: KeyManagementService, @@ -47,7 +46,6 @@ class Engine { logger.debug("invite sent on topic: \(topic)") } - func accept(inviteId: String) async throws { guard let hexPubKey = try topicToInvitationPubKeyStore.get(key: "todo-topic") else { throw ChatError.noPublicKeyForInviteId diff --git a/Sources/Chat/NetworkingInteractor.swift b/Sources/Chat/NetworkingInteractor.swift index 8cdd1b44c..66fced10a 100644 --- a/Sources/Chat/NetworkingInteractor.swift +++ b/Sources/Chat/NetworkingInteractor.swift @@ -1,11 +1,10 @@ - import Foundation import Combine import WalletConnectRelay import WalletConnectUtils protocol NetworkInteracting { - func subscribe(topic: String) async throws + func subscribe(topic: String) async throws } class NetworkingInteractor: NetworkInteracting { @@ -15,7 +14,7 @@ class NetworkingInteractor: NetworkInteracting { requestPublisherSubject.eraseToAnyPublisher() } private let requestPublisherSubject = PassthroughSubject() - + var responsePublisher: AnyPublisher { responsePublisherSubject.eraseToAnyPublisher() } @@ -25,30 +24,30 @@ class NetworkingInteractor: NetworkInteracting { serializer: Serializing) { self.relayClient = relayClient self.serializer = serializer - + relayClient.onMessage = { [unowned self] topic, message in manageSubscription(topic, message) } } - + func requestUnencrypted(_ request: ChatRequest, topic: String) { let message = try! request.json() - relayClient.publish(topic: topic, payload: message) {error in + relayClient.publish(topic: topic, payload: message) {_ in // print(error) } } - + func request(_ request: ChatRequest, topic: String) { let message = try! serializer.serialize(topic: topic, encodable: request) - relayClient.publish(topic: topic, payload: message) {error in + relayClient.publish(topic: topic, payload: message) {_ in // print(error) } } - + func subscribe(topic: String) async throws { try await relayClient.subscribe(topic: topic) } - + private func manageSubscription(_ topic: String, _ message: String) { if let deserializedJsonRpcRequest: ChatRequest = serializer.tryDeserialize(topic: topic, message: message) { handleWCRequest(topic: topic, request: deserializedJsonRpcRequest) @@ -63,26 +62,25 @@ class NetworkingInteractor: NetworkInteracting { print("Warning: WalletConnect Relay - Received unknown object type from networking relay") } } - - + private func tryDecodeRequest(message: String) -> ChatRequest? { guard let messageData = message.data(using: .utf8) else { return nil } return try? JSONDecoder().decode(ChatRequest.self, from: messageData) } - + private func handleWCRequest(topic: String, request: ChatRequest) { let payload = RequestSubscriptionPayload(topic: topic, request: request) requestPublisherSubject.send(payload) } - + private func handleJsonRpcResponse(response: JSONRPCResponse) { - //todo + // todo } - + private func handleJsonRpcErrorResponse(response: JSONRPCErrorResponse) { - //todo + // todo } - + } diff --git a/Sources/Chat/Registry.swift b/Sources/Chat/Registry.swift index f01eaa7fc..ab855d30c 100644 --- a/Sources/Chat/Registry.swift +++ b/Sources/Chat/Registry.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils @@ -7,17 +6,16 @@ protocol Registry { func resolve(account: Account) async throws -> String } -actor KeyValueRegistry: Registry { - +actor KeyValueRegistry: Registry { + private var registryStore: [Account: String] = [:] - + func register(account address: Account, pubKey: String) async throws { registryStore[address] = pubKey } - + func resolve(account: Account) async throws -> String { guard let record = registryStore[account] else { throw ChatError.recordNotFound} return record } } - diff --git a/Sources/Chat/RegistryManager.swift b/Sources/Chat/RegistryManager.swift index ff0d84116..fde863809 100644 --- a/Sources/Chat/RegistryManager.swift +++ b/Sources/Chat/RegistryManager.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils import WalletConnectKMS @@ -9,7 +8,7 @@ actor RegistryManager { let registry: Registry let logger: ConsoleLogging let kms: KeyManagementServiceProtocol - + init(registry: Registry, networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, @@ -21,7 +20,7 @@ actor RegistryManager { self.logger = logger self.topicToInvitationPubKeyStore = topicToInvitationPubKeyStore } - + func register(account: Account) async throws -> String { let pubKey = try kms.createX25519KeyPair() let pubKeyHex = pubKey.hexRepresentation diff --git a/Sources/Chat/Serializing.swift b/Sources/Chat/Serializing.swift index abcf159b6..b3af40940 100644 --- a/Sources/Chat/Serializing.swift +++ b/Sources/Chat/Serializing.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectKMS diff --git a/Sources/Chat/StorageDomainIdentifiers.swift b/Sources/Chat/StorageDomainIdentifiers.swift index 6ca44a5a6..574f5525b 100644 --- a/Sources/Chat/StorageDomainIdentifiers.swift +++ b/Sources/Chat/StorageDomainIdentifiers.swift @@ -1,4 +1,3 @@ - import Foundation enum StorageDomainIdentifiers: String { diff --git a/Sources/Chat/Types/ChatError.swift b/Sources/Chat/Types/ChatError.swift index 6c3dafbe9..96b71ce0e 100644 --- a/Sources/Chat/Types/ChatError.swift +++ b/Sources/Chat/Types/ChatError.swift @@ -1,4 +1,3 @@ - import Foundation enum ChatError: Error { diff --git a/Sources/Chat/Types/ChatRequest.swift b/Sources/Chat/Types/ChatRequest.swift index cbbf372a4..9fe2b075d 100644 --- a/Sources/Chat/Types/ChatRequest.swift +++ b/Sources/Chat/Types/ChatRequest.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils @@ -7,27 +6,26 @@ struct ChatRequest: Codable { let jsonrpc: String let method: Method let params: Params - + enum CodingKeys: CodingKey { case id case jsonrpc case method case params } - + internal init(id: Int64 = generateId(), jsonrpc: String = "2.0", params: Params) { self.id = id self.jsonrpc = jsonrpc self.params = params switch params { - case .invite(_): + case .invite: self.method = Method.invite - case .message(_): + case .message: self.method = Method.message } } - - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int64.self, forKey: .id) @@ -42,7 +40,7 @@ struct ChatRequest: Codable { params = .message(paramsValue) } } - + func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) @@ -55,7 +53,7 @@ struct ChatRequest: Codable { try container.encode(params, forKey: .params) } } - + private static func generateId() -> Int64 { return Int64(Date().timeIntervalSince1970 * 1000)*1000 + Int64.random(in: 0..<1000) } diff --git a/Sources/Chat/Types/ChatResponse.swift b/Sources/Chat/Types/ChatResponse.swift index 02aa56b84..54ba8beb5 100644 --- a/Sources/Chat/Types/ChatResponse.swift +++ b/Sources/Chat/Types/ChatResponse.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils @@ -8,4 +7,3 @@ struct ChatResponse: Codable { let requestParams: ChatRequest.Params let result: JsonRpcResult } - diff --git a/Sources/Chat/Types/Invite.swift b/Sources/Chat/Types/Invite.swift index e772538b8..618ae4e48 100644 --- a/Sources/Chat/Types/Invite.swift +++ b/Sources/Chat/Types/Invite.swift @@ -1,14 +1,10 @@ - - import Foundation struct Invite: Codable { let pubKey: String let openingMessage: String - + var id: String { return pubKey } } - - diff --git a/Sources/Chat/Types/RequestSubscriptionPayload.swift b/Sources/Chat/Types/RequestSubscriptionPayload.swift index 967a2cb2d..d7a8066e9 100644 --- a/Sources/Chat/Types/RequestSubscriptionPayload.swift +++ b/Sources/Chat/Types/RequestSubscriptionPayload.swift @@ -1,5 +1,3 @@ - - import Foundation struct RequestSubscriptionPayload: Codable { diff --git a/Sources/Chat/Types/Thread.swift b/Sources/Chat/Types/Thread.swift index cce2449a1..391a87dfe 100644 --- a/Sources/Chat/Types/Thread.swift +++ b/Sources/Chat/Types/Thread.swift @@ -1,9 +1,7 @@ - - import Foundation struct Thread: Codable { let topic: String let pubKey: String - //let peerName: String + // let peerName: String } diff --git a/Sources/Commons/AnyCodable.swift b/Sources/Commons/AnyCodable.swift index f292a0d9f..34fe575af 100644 --- a/Sources/Commons/AnyCodable.swift +++ b/Sources/Commons/AnyCodable.swift @@ -13,17 +13,17 @@ import Foundation You can call `get(_:)` to transform the underlying value back to the type you specify. */ public struct AnyCodable { - + public let value: Any - + private var dataEncoding: (() throws -> Data)? - + private var genericEncoding: ((Encoder) throws -> Void)? - + private init(_ value: Any) { self.value = value } - + /** Creates a type-erased codable value that wraps the given instance. @@ -40,9 +40,9 @@ public struct AnyCodable { genericEncoding = { encoder in try codable.encode(to: encoder) } - + } - + /** Returns the underlying value, provided it matches the type spcified. @@ -66,7 +66,7 @@ public struct AnyCodable { let valueData = try getDataRepresentation() return try JSONDecoder().decode(type, from: valueData) } - + /// A textual representation of the underlying encoded data. Returns an empty string if the type fails to encode. public var stringRepresentation: String { guard @@ -77,7 +77,7 @@ public struct AnyCodable { } return string } - + private func getDataRepresentation() throws -> Data { if let encodeToData = dataEncoding { return try encodeToData() @@ -88,7 +88,7 @@ public struct AnyCodable { } extension AnyCodable: Equatable { - + public static func == (lhs: AnyCodable, rhs: AnyCodable) -> Bool { do { let lhsData = try lhs.getDataRepresentation() @@ -107,7 +107,7 @@ extension AnyCodable: Hashable { } extension AnyCodable: CustomStringConvertible { - + public var description: String { let stringSelf = stringRepresentation let description = stringSelf.isEmpty ? "invalid data" : stringSelf @@ -116,23 +116,23 @@ extension AnyCodable: CustomStringConvertible { } extension AnyCodable: Decodable, Encodable { - + struct CodingKeys: CodingKey { - + let stringValue: String let intValue: Int? - + init?(intValue: Int) { self.stringValue = String(intValue) self.intValue = intValue } - + init?(stringValue: String) { self.stringValue = stringValue self.intValue = Int(stringValue) } } - + public init(from decoder: Decoder) throws { if let container = try? decoder.container(keyedBy: CodingKeys.self) { var result = [String: Any]() @@ -140,15 +140,13 @@ extension AnyCodable: Decodable, Encodable { result[key.stringValue] = try container.decode(AnyCodable.self, forKey: key).value } value = result - } - else if var container = try? decoder.unkeyedContainer() { + } else if var container = try? decoder.unkeyedContainer() { var result = [Any]() while !container.isAtEnd { result.append(try container.decode(AnyCodable.self).value) } value = result - } - else if let container = try? decoder.singleValueContainer() { + } else if let container = try? decoder.singleValueContainer() { if let intVal = try? container.decode(Int.self) { value = intVal } else if let doubleVal = try? container.decode(Double.self) { @@ -164,7 +162,7 @@ extension AnyCodable: Decodable, Encodable { throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No data found in the decoder.")) } } - + public func encode(to encoder: Encoder) throws { if let encoding = genericEncoding { try encoding(encoder) diff --git a/Sources/JSONRPC/JSONRPCError.swift b/Sources/JSONRPC/JSONRPCError.swift index 8c2bbdd60..7cca56ad9 100644 --- a/Sources/JSONRPC/JSONRPCError.swift +++ b/Sources/JSONRPC/JSONRPCError.swift @@ -4,7 +4,7 @@ public struct JSONRPCError: Error, Equatable, Codable { public let code: Int public let message: String public let data: AnyCodable? - + public init(code: Int, message: String, data: AnyCodable? = nil) { self.code = code self.message = message diff --git a/Sources/JSONRPC/RPCID.swift b/Sources/JSONRPC/RPCID.swift index f8ef5a2da..a4a7bec7e 100644 --- a/Sources/JSONRPC/RPCID.swift +++ b/Sources/JSONRPC/RPCID.swift @@ -7,7 +7,7 @@ public protocol IdentifierGenerator { } struct IntIdentifierGenerator: IdentifierGenerator { - + func next() -> RPCID { return RPCID(Int.random(in: Int.min...Int.max)) } diff --git a/Sources/JSONRPC/RPCRequest.swift b/Sources/JSONRPC/RPCRequest.swift index ff41d502e..473550899 100644 --- a/Sources/JSONRPC/RPCRequest.swift +++ b/Sources/JSONRPC/RPCRequest.swift @@ -4,39 +4,39 @@ import Commons TODO: Add documentation */ public struct RPCRequest: Equatable { - + enum Error: Swift.Error { case invalidPrimitiveParameter } - + public static var defaultIdentifierGenerator: IdentifierGenerator = IntIdentifierGenerator() - + public let jsonrpc: String - + public let method: String - + public let params: AnyCodable? - + public let id: RPCID? - + internal init(method: String, params: AnyCodable?, id: RPCID?) { self.jsonrpc = "2.0" self.method = method self.params = params self.id = id } - + internal init(method: String, checkedParams params: C, id: RPCID) throws where C: Codable { if params is Int || params is Double || params is String || params is Bool { throw Error.invalidPrimitiveParameter } self.init(method: method, params: AnyCodable(params), id: id) } - + public init(method: String, checkedParams params: C, idGenerator: IdentifierGenerator = defaultIdentifierGenerator) throws where C: Codable { try self.init(method: method, checkedParams: params, id: idGenerator.next()) } - + public init(method: String, checkedParams params: C, id: Int) throws where C: Codable { try self.init(method: method, checkedParams: params, id: .right(id)) } @@ -44,7 +44,7 @@ public struct RPCRequest: Equatable { public init(method: String, checkedParams params: C, id: String) throws where C: Codable { try self.init(method: method, checkedParams: params, id: .left(id)) } - + public init(method: String, params: C, idGenerator: IdentifierGenerator = defaultIdentifierGenerator) where C: Codable { self.init(method: method, params: AnyCodable(params), id: idGenerator.next()) } @@ -56,37 +56,37 @@ public struct RPCRequest: Equatable { public init(method: String, params: C, id: String) where C: Codable { self.init(method: method, params: AnyCodable(params), id: .left(id)) } - + public init(method: String, idGenerator: IdentifierGenerator = defaultIdentifierGenerator) { self.init(method: method, params: nil, id: idGenerator.next()) } - + public init(method: String, id: Int) { self.init(method: method, params: nil, id: .right(id)) } - + public init(method: String, id: String) { self.init(method: method, params: nil, id: .left(id)) } } extension RPCRequest { - + static func notification(method: String, params: C) -> RPCRequest where C: Codable { return RPCRequest(method: method, params: AnyCodable(params), id: nil) } - + static func notification(method: String) -> RPCRequest { return RPCRequest(method: method, params: nil, id: nil) } - + public var isNotification: Bool { return id == nil } } extension RPCRequest: Codable { - + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) jsonrpc = try container.decode(String.self, forKey: .jsonrpc) diff --git a/Sources/JSONRPC/RPCResponse.swift b/Sources/JSONRPC/RPCResponse.swift index c811f608b..0934adb7e 100644 --- a/Sources/JSONRPC/RPCResponse.swift +++ b/Sources/JSONRPC/RPCResponse.swift @@ -4,67 +4,67 @@ import Commons TODO: Add documentation */ public struct RPCResponse: Equatable { - + public let jsonrpc: String - + public let id: RPCID? - + public var result: AnyCodable? { if case .success(let value) = outcome { return value } return nil } - + public var error: JSONRPCError? { if case .failure(let error) = outcome { return error } return nil } - + private let outcome: Result - + internal init(id: RPCID?, outcome: Result) { self.jsonrpc = "2.0" self.id = id self.outcome = outcome } - + public init(id: Int, result: C) where C: Codable { self.init(id: RPCID(id), outcome: .success(AnyCodable(result))) } - + public init(id: String, result: C) where C: Codable { self.init(id: RPCID(id), outcome: .success(AnyCodable(result))) } - + public init(id: Int, error: JSONRPCError) { self.init(id: RPCID(id), outcome: .failure(error)) } - + public init(id: String, error: JSONRPCError) { self.init(id: RPCID(id), outcome: .failure(error)) } - + public init(id: Int, errorCode: Int, message: String, associatedData: AnyCodable? = nil) { self.init(id: RPCID(id), outcome: .failure(JSONRPCError(code: errorCode, message: message, data: associatedData))) } - + public init(id: String, errorCode: Int, message: String, associatedData: AnyCodable? = nil) { self.init(id: RPCID(id), outcome: .failure(JSONRPCError(code: errorCode, message: message, data: associatedData))) } - + public init(errorWithoutID: JSONRPCError) { self.init(id: nil, outcome: .failure(errorWithoutID)) } } extension RPCResponse: Codable { - + enum CodingKeys: CodingKey { case jsonrpc case result case error case id } - + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) jsonrpc = try container.decode(String.self, forKey: .jsonrpc) @@ -97,7 +97,7 @@ extension RPCResponse: Codable { debugDescription: "Couldn't find neither a result nor an error in the response.")) } } - + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(jsonrpc, forKey: .jsonrpc) diff --git a/Sources/WalletConnectKMS/Codec/ChaChaPolyCodec.swift b/Sources/WalletConnectKMS/Codec/ChaChaPolyCodec.swift index b402b9b2e..c95cfc5e1 100644 --- a/Sources/WalletConnectKMS/Codec/ChaChaPolyCodec.swift +++ b/Sources/WalletConnectKMS/Codec/ChaChaPolyCodec.swift @@ -21,7 +21,7 @@ class ChaChaPolyCodec: Codec { let sealBox = try ChaChaPoly.seal(dataToSeal, using: key, nonce: nonce) return sealBox.combined.base64EncodedString() } - + func decode(sealboxString: String, symmetricKey: Data) throws -> Data { guard let sealboxData = Data(base64Encoded: sealboxString) else { throw CodecError.malformedSealbox diff --git a/Sources/WalletConnectKMS/Crypto/AgreementKeys.swift b/Sources/WalletConnectKMS/Crypto/AgreementKeys.swift index a42b80ea5..1333de5bf 100644 --- a/Sources/WalletConnectKMS/Crypto/AgreementKeys.swift +++ b/Sources/WalletConnectKMS/Crypto/AgreementKeys.swift @@ -1,10 +1,10 @@ import Foundation public struct AgreementKeys: Equatable { - + public let sharedKey: SymmetricKey public let publicKey: AgreementPublicKey - + public func derivedTopic() -> String { sharedKey.rawRepresentation.sha256().toHexString() } @@ -14,7 +14,7 @@ extension AgreementKeys: GenericPasswordConvertible { enum Error: Swift.Error { case invalidBufferLenght } - public init(rawRepresentation data: D) throws where D : ContiguousBytes { + public init(rawRepresentation data: D) throws where D: ContiguousBytes { let buffer = data.withUnsafeBytes { Data($0) } guard buffer.count == 64 else { throw Error.invalidBufferLenght @@ -23,7 +23,7 @@ extension AgreementKeys: GenericPasswordConvertible { self.sharedKey = try SymmetricKey(rawRepresentation: symKeyRaw) self.publicKey = try AgreementPublicKey(rawRepresentation: buffer.subdata(in: 32..<64)) } - + public var rawRepresentation: Data { sharedKey.rawRepresentation + publicKey.rawRepresentation } diff --git a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/CryptoKitWrapper.swift b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/CryptoKitWrapper.swift index d29c6bbd7..fa88f1001 100644 --- a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/CryptoKitWrapper.swift +++ b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/CryptoKitWrapper.swift @@ -18,38 +18,38 @@ extension Curve25519.KeyAgreement.PrivateKey: Equatable { // MARK: - Public Key public struct AgreementPublicKey: Equatable { - + fileprivate let key: Curve25519.KeyAgreement.PublicKey - + fileprivate init(publicKey: Curve25519.KeyAgreement.PublicKey) { self.key = publicKey } - + public init(rawRepresentation data: D) throws where D: ContiguousBytes { self.key = try Curve25519.KeyAgreement.PublicKey(rawRepresentation: data) } - + public init(hex: String) throws { let data = Data(hex: hex) try self.init(rawRepresentation: data) } - + public var rawRepresentation: Data { key.rawRepresentation } - + public var hexRepresentation: String { key.rawRepresentation.toHexString() } } extension AgreementPublicKey: Codable { - + public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(key.rawRepresentation) } - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let buffer = try container.decode(Data.self) @@ -62,23 +62,23 @@ extension AgreementPublicKey: Codable { public struct AgreementPrivateKey: GenericPasswordConvertible, Equatable { private let key: Curve25519.KeyAgreement.PrivateKey - + public init() { self.key = Curve25519.KeyAgreement.PrivateKey() } - - public init(rawRepresentation: D) throws where D : ContiguousBytes { + + public init(rawRepresentation: D) throws where D: ContiguousBytes { self.key = try Curve25519.KeyAgreement.PrivateKey(rawRepresentation: rawRepresentation) } - + public var rawRepresentation: Data { key.rawRepresentation } - + public var publicKey: AgreementPublicKey { AgreementPublicKey(publicKey: key.publicKey) } - + func sharedSecretFromKeyAgreement(with publicKeyShare: AgreementPublicKey) throws -> SharedSecret { let sharedSecret = try key.sharedSecretFromKeyAgreement(with: publicKeyShare.key) return SharedSecret(sharedSecret: sharedSecret) diff --git a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SharedSecret.swift b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SharedSecret.swift index ca1658c3d..a0ec08f89 100644 --- a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SharedSecret.swift +++ b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SharedSecret.swift @@ -1,4 +1,3 @@ - import Foundation import CryptoKit @@ -7,11 +6,11 @@ struct SharedSecret { var rawRepresentation: Data { return sharedSecret.withUnsafeBytes { return Data(Array($0)) } } - + init(sharedSecret: CryptoKit.SharedSecret) { self.sharedSecret = sharedSecret } - + func deriveSymmetricKey() -> SymmetricKey { let symKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: Data(), sharedInfo: Data(), outputByteCount: 32) return SymmetricKey(key: symKey) diff --git a/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift index 5eeb63cec..10eb04dde 100644 --- a/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift +++ b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift @@ -22,17 +22,17 @@ public class KeyManagementService: KeyManagementServiceProtocol { enum Error: Swift.Error { case keyNotFound } - + private var keychain: KeychainStorageProtocol - + public init(serviceIdentifier: String) { - self.keychain = KeychainStorage(serviceIdentifier: serviceIdentifier) + self.keychain = KeychainStorage(serviceIdentifier: serviceIdentifier) } - + init(keychain: KeychainStorageProtocol) { self.keychain = keychain } - + public func createX25519KeyPair() throws -> AgreementPublicKey { let privateKey = AgreementPrivateKey() try setPrivateKey(privateKey) @@ -44,19 +44,19 @@ public class KeyManagementService: KeyManagementServiceProtocol { try setSymmetricKey(key, for: topic) return key } - + public func setSymmetricKey(_ symmetricKey: SymmetricKey, for topic: String) throws { try keychain.add(symmetricKey, forKey: topic) } - + public func setPrivateKey(_ privateKey: AgreementPrivateKey) throws { try keychain.add(privateKey, forKey: privateKey.publicKey.hexRepresentation) } - + public func setAgreementSecret(_ agreementSecret: AgreementKeys, topic: String) throws { try keychain.add(agreementSecret, forKey: topic) } - + public func getSymmetricKey(for topic: String) throws -> SymmetricKey? { do { return try keychain.read(key: topic) as SymmetricKey @@ -64,7 +64,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { return nil } } - + public func getSymmetricKeyRepresentable(for topic: String) -> Data? { if let key = try? getAgreementSecret(for: topic)?.sharedKey { return key.rawRepresentation @@ -72,7 +72,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { return try? getSymmetricKey(for: topic)?.rawRepresentation } } - + public func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? { do { return try keychain.read(key: publicKey.hexRepresentation) as AgreementPrivateKey @@ -82,7 +82,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { throw error } } - + public func getAgreementSecret(for topic: String) throws -> AgreementKeys? { do { return try keychain.read(key: topic) as AgreementKeys @@ -90,7 +90,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { return nil } } - + public func deletePrivateKey(for publicKey: String) { do { try keychain.delete(key: publicKey) @@ -98,7 +98,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { print("Error deleting private key: \(error)") } } - + public func deleteAgreementSecret(for topic: String) { do { try keychain.delete(key: topic) @@ -106,7 +106,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { print("Error deleting agreement key: \(error)") } } - + public func deleteSymmetricKey(for topic: String) { do { try keychain.delete(key: topic) @@ -114,7 +114,7 @@ public class KeyManagementService: KeyManagementServiceProtocol { print("Error deleting symmetric key: \(error)") } } - + public func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementKeys { guard let privateKey = try getPrivateKey(for: selfPublicKey) else { print("Key Agreement Error: Private key not found for public key: \(selfPublicKey.hexRepresentation)") @@ -122,11 +122,11 @@ public class KeyManagementService: KeyManagementServiceProtocol { } return try KeyManagementService.generateAgreementKey(from: privateKey, peerPublicKey: hexRepresentation) } - + public func deleteAll() throws { try keychain.deleteAll() } - + static func generateAgreementKey(from privateKey: AgreementPrivateKey, peerPublicKey hexRepresentation: String) throws -> AgreementKeys { let peerPublicKey = try AgreementPublicKey(rawRepresentation: Data(hex: hexRepresentation)) let sharedSecret = try privateKey.sharedSecretFromKeyAgreement(with: peerPublicKey) @@ -134,5 +134,3 @@ public class KeyManagementService: KeyManagementServiceProtocol { return AgreementKeys(sharedKey: sharedKey, publicKey: privateKey.publicKey) } } - - diff --git a/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift b/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift index 377243904..7e2863f3c 100644 --- a/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift +++ b/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift @@ -1,16 +1,14 @@ - import Foundation import CryptoKit - public struct SymmetricKey: Equatable { - + private let key: CryptoKit.SymmetricKey - + public var hexRepresentation: String { rawRepresentation.toHexString() } - + public init(key: CryptoKit.SymmetricKey) { self.key = key } @@ -21,7 +19,7 @@ public struct SymmetricKey: Equatable { self.key = CryptoKit.SymmetricKey(size: SymmetricKeySize.bits256) } } - + public init(hex: String) throws { let data = Data(hex: hex) try self.init(rawRepresentation: data) @@ -30,17 +28,16 @@ public struct SymmetricKey: Equatable { } extension SymmetricKey: GenericPasswordConvertible { - + public var rawRepresentation: Data { key.withUnsafeBytes {Data(Array($0))} } - - public init(rawRepresentation data: D) throws where D : ContiguousBytes { + + public init(rawRepresentation data: D) throws where D: ContiguousBytes { self.key = CryptoKit.SymmetricKey(data: data) } } - extension SymmetricKey { public enum Size { case bits256 diff --git a/Sources/WalletConnectKMS/Keychain/KeychainError.swift b/Sources/WalletConnectKMS/Keychain/KeychainError.swift index 489bdbd18..37974619c 100644 --- a/Sources/WalletConnectKMS/Keychain/KeychainError.swift +++ b/Sources/WalletConnectKMS/Keychain/KeychainError.swift @@ -2,16 +2,16 @@ import Foundation // TODO: Integrate with WalletConnectError struct KeychainError: Error { - + let status: OSStatus - + init(_ status: OSStatus) { self.status = status } } extension KeychainError: CustomStringConvertible { - + var description: String { status.message } diff --git a/Sources/WalletConnectKMS/Keychain/KeychainService.swift b/Sources/WalletConnectKMS/Keychain/KeychainService.swift index f25c9aa35..02a8518d4 100644 --- a/Sources/WalletConnectKMS/Keychain/KeychainService.swift +++ b/Sources/WalletConnectKMS/Keychain/KeychainService.swift @@ -8,19 +8,19 @@ protocol KeychainServiceProtocol { } final class KeychainServiceWrapper: KeychainServiceProtocol { - + func add(_ attributes: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { return SecItemAdd(attributes, result) } - + func copyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { return SecItemCopyMatching(query, result) } - + func update(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus { return SecItemUpdate(query, attributesToUpdate) } - + func delete(_ query: CFDictionary) -> OSStatus { return SecItemDelete(query) } diff --git a/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift index 44c049859..2f5857192 100644 --- a/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift +++ b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift @@ -8,45 +8,45 @@ protocol KeychainStorageProtocol { } final class KeychainStorage: KeychainStorageProtocol { - + private let service: String - + private let secItem: KeychainServiceProtocol - + init(keychainService: KeychainServiceProtocol = KeychainServiceWrapper(), serviceIdentifier: String) { self.secItem = keychainService service = serviceIdentifier } - - func add(_ item: T, forKey key: String) throws where T : GenericPasswordConvertible { + + func add(_ item: T, forKey key: String) throws where T: GenericPasswordConvertible { try add(data: item.rawRepresentation, forKey: key) } - + func add(data: Data, forKey key: String) throws { var query = buildBaseServiceQuery(for: key) query[kSecValueData] = data - + let status = secItem.add(query as CFDictionary, nil) - + guard status == errSecSuccess else { throw KeychainError(status) } } - - func read(key: String) throws -> T where T : GenericPasswordConvertible { + + func read(key: String) throws -> T where T: GenericPasswordConvertible { guard let data = try readData(key: key) else { throw KeychainError(errSecItemNotFound) } return try T(rawRepresentation: data) } - + func readData(key: String) throws -> Data? { var query = buildBaseServiceQuery(for: key) query[kSecReturnData] = true - + var item: CFTypeRef? let status = secItem.copyMatching(query as CFDictionary, &item) - + switch status { case errSecSuccess: return item as? Data @@ -56,32 +56,32 @@ final class KeychainStorage: KeychainStorageProtocol { throw KeychainError(status) } } - - func update(_ item: T, forKey key: String) throws where T : GenericPasswordConvertible { + + func update(_ item: T, forKey key: String) throws where T: GenericPasswordConvertible { try update(data: item.rawRepresentation, forKey: key) } - + func update(data: Data, forKey key: String) throws { let query = buildBaseServiceQuery(for: key) let attributes = [kSecValueData: data] - + let status = secItem.update(query as CFDictionary, attributes as CFDictionary) - + guard status == errSecSuccess else { throw KeychainError(status) } } - + func delete(key: String) throws { let query = buildBaseServiceQuery(for: key) - + let status = secItem.delete(query as CFDictionary) - + guard status == errSecSuccess || status == errSecItemNotFound else { throw KeychainError(status) } } - + func deleteAll() throws { let query = [ kSecClass: kSecClassGenericPassword, @@ -92,7 +92,7 @@ final class KeychainStorage: KeychainStorageProtocol { throw KeychainError(status) } } - + private func buildBaseServiceQuery(for key: String) -> [CFString: Any] { return [ kSecClass: kSecClassGenericPassword, diff --git a/Sources/WalletConnectKMS/Serialiser/Serializer.swift b/Sources/WalletConnectKMS/Serialiser/Serializer.swift index 8393766a4..0f8458e13 100644 --- a/Sources/WalletConnectKMS/Serialiser/Serializer.swift +++ b/Sources/WalletConnectKMS/Serialiser/Serializer.swift @@ -1,24 +1,23 @@ import Foundation import WalletConnectUtils - public class Serializer { enum Error: String, Swift.Error { case symmetricKeyForTopicNotFound } private let kms: KeyManagementServiceProtocol private let codec: Codec - + init(kms: KeyManagementServiceProtocol, codec: Codec = ChaChaPolyCodec()) { self.kms = kms self.codec = codec } - + public init(kms: KeyManagementService) { self.kms = kms self.codec = ChaChaPolyCodec() } - + /// Encrypts and serializes an object /// - Parameters: /// - topic: Topic that is associated with a symetric key for encrypting particular codable object @@ -32,7 +31,7 @@ public class Serializer { throw Error.symmetricKeyForTopicNotFound } } - + /// Deserializes and decrypts an object /// - Parameters: /// - topic: Topic that is associated with a symetric key for decrypting particular codable object @@ -49,10 +48,9 @@ public class Serializer { return nil } } - + private func deserialize(message: String, symmetricKey: Data) throws -> T { let decryptedData = try codec.decode(sealboxString: message, symmetricKey: symmetricKey) return try JSONDecoder().decode(T.self, from: decryptedData) } } - diff --git a/Sources/WalletConnectRelay/AppStateObserving.swift b/Sources/WalletConnectRelay/AppStateObserving.swift index 777658cd0..fec2c7a06 100644 --- a/Sources/WalletConnectRelay/AppStateObserving.swift +++ b/Sources/WalletConnectRelay/AppStateObserving.swift @@ -1,23 +1,22 @@ - import Foundation #if os(iOS) import UIKit #endif protocol AppStateObserving { - var onWillEnterForeground: (()->())? {get set} - var onWillEnterBackground: (()->())? {get set} + var onWillEnterForeground: (() -> Void)? {get set} + var onWillEnterBackground: (() -> Void)? {get set} } class AppStateObserver: AppStateObserving { - @objc var onWillEnterForeground: (() -> ())? - - @objc var onWillEnterBackground: (() -> ())? - + @objc var onWillEnterForeground: (() -> Void)? + + @objc var onWillEnterBackground: (() -> Void)? + init() { subscribeNotificationCenter() } - + private func subscribeNotificationCenter() { #if os(iOS) NotificationCenter.default.addObserver( @@ -32,17 +31,15 @@ class AppStateObserver: AppStateObserving { object: nil) #endif } - + @objc private func appWillEnterBackground() { onWillEnterBackground?() } - + @objc private func appWillEnterForeground() { onWillEnterForeground?() } - -} - +} diff --git a/Sources/WalletConnectRelay/Dispatching.swift b/Sources/WalletConnectRelay/Dispatching.swift index 812e73108..51b72cdef 100644 --- a/Sources/WalletConnectRelay/Dispatching.swift +++ b/Sources/WalletConnectRelay/Dispatching.swift @@ -3,24 +3,24 @@ import WalletConnectUtils import Starscream protocol Dispatching { - var onConnect: (()->())? {get set} - var onDisconnect: (()->())? {get set} - var onMessage: ((String) -> ())? {get set} + var onConnect: (() -> Void)? {get set} + var onDisconnect: (() -> Void)? {get set} + var onMessage: ((String) -> Void)? {get set} func send(_ string: String) async throws - func send(_ string: String, completion: @escaping (Error?)->()) + func send(_ string: String, completion: @escaping (Error?) -> Void) func connect() throws func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws } final class Dispatcher: NSObject, Dispatching { - var onConnect: (() -> ())? - var onDisconnect: (() -> ())? - var onMessage: ((String) -> ())? + var onConnect: (() -> Void)? + var onDisconnect: (() -> Void)? + var onMessage: ((String) -> Void)? private var textFramesQueue = Queue() private let logger: ConsoleLogging var socket: WebSocketProtocol var socketConnectionHandler: SocketConnectionHandler - + init(socket: WebSocketProtocol, socketConnectionHandler: SocketConnectionHandler, logger: ConsoleLogging) { @@ -43,44 +43,44 @@ final class Dispatcher: NSObject, Dispatching { } } } - + func send(_ string: String, completion: @escaping (Error?) -> Void) { - //TODO - add policy for retry and "single try" + // TODO - add policy for retry and "single try" if socket.isConnected { self.socket.write(string: string) { completion(nil) } - //TODO - enqueue if fails + // TODO - enqueue if fails } else { completion(NetworkError.webSocketNotConnected) // textFramesQueue.enqueue(string) } } - + func connect() throws { try socketConnectionHandler.handleConnect() } - + func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws { try socketConnectionHandler.handleDisconnect(closeCode: closeCode) } - + private func setUpWebSocketSession() { socket.onText = { [weak self] in self?.onMessage?($0) } } - + private func setUpSocketConnectionObserving() { socket.onConnect = { [weak self] in self?.dequeuePendingTextFrames() self?.onConnect?() } - socket.onDisconnect = { [weak self] error in + socket.onDisconnect = { [weak self] _ in self?.onDisconnect?() } } - + private func dequeuePendingTextFrames() { while let frame = textFramesQueue.dequeue() { send(frame) { error in diff --git a/Sources/WalletConnectRelay/Misc/NetworkError.swift b/Sources/WalletConnectRelay/Misc/NetworkError.swift index 46acca2bd..62a384ff0 100644 --- a/Sources/WalletConnectRelay/Misc/NetworkError.swift +++ b/Sources/WalletConnectRelay/Misc/NetworkError.swift @@ -5,7 +5,7 @@ enum NetworkError: Error { } extension NetworkError { - + var localizedDescription: String { switch self { case .webSocketNotConnected: diff --git a/Sources/WalletConnectRelay/NetworkMonitoring.swift b/Sources/WalletConnectRelay/NetworkMonitoring.swift index 61bbdd5ab..66fe0a88c 100644 --- a/Sources/WalletConnectRelay/NetworkMonitoring.swift +++ b/Sources/WalletConnectRelay/NetworkMonitoring.swift @@ -1,20 +1,19 @@ - import Foundation import Network protocol NetworkMonitoring { - var onSatisfied: (()->())? {get set} - var onUnsatisfied: (()->())? {get set} + var onSatisfied: (() -> Void)? {get set} + var onUnsatisfied: (() -> Void)? {get set} func startMonitoring() } class NetworkMonitor: NetworkMonitoring { - var onSatisfied: (() -> ())? - var onUnsatisfied: (() -> ())? - + var onSatisfied: (() -> Void)? + var onUnsatisfied: (() -> Void)? + private let monitor = NWPathMonitor() private let monitorQueue = DispatchQueue(label: "com.walletconnect.sdk.network.monitor") - + func startMonitoring() { monitor.pathUpdateHandler = { [weak self] path in if path.status == .satisfied { @@ -26,4 +25,3 @@ class NetworkMonitor: NetworkMonitoring { monitor.start(queue: monitorQueue) } } - diff --git a/Sources/WalletConnectRelay/RelayClient.swift b/Sources/WalletConnectRelay/RelayClient.swift index 972ecf44e..ce8d255ba 100644 --- a/Sources/WalletConnectRelay/RelayClient.swift +++ b/Sources/WalletConnectRelay/RelayClient.swift @@ -1,4 +1,3 @@ - import Foundation import Combine import WalletConnectUtils @@ -17,11 +16,11 @@ public final class RelayClient { private let concurrentQueue = DispatchQueue(label: "com.walletconnect.sdk.relay_client", attributes: .concurrent) let jsonRpcSubscriptionsHistory: JsonRpcHistory - public var onMessage: ((String, String) -> ())? + public var onMessage: ((String, String) -> Void)? private var dispatcher: Dispatching var subscriptions: [String: String] = [:] let defaultTtl = 6*Time.hour - + public var socketConnectionStatusPublisher: AnyPublisher { socketConnectionStatusPublisherSubject.eraseToAnyPublisher() } @@ -37,17 +36,17 @@ public final class RelayClient { private let requestAcknowledgePublisherSubject = PassthroughSubject, Never>() let logger: ConsoleLogging static let historyIdentifier = "com.walletconnect.sdk.relayer_client.subscription_json_rpc_record" - + init(dispatcher: Dispatching, logger: ConsoleLogging, keyValueStorage: KeyValueStorage) { self.logger = logger self.dispatcher = dispatcher - + self.jsonRpcSubscriptionsHistory = JsonRpcHistory(logger: logger, keyValueStore: CodableStore(defaults: keyValueStorage, identifier: Self.historyIdentifier)) setUpBindings() } - + /// Instantiates Relay Client /// - Parameters: /// - relayHost: proxy server host that your application will use to connect to Waku Network. If you register your project at `www.walletconnect.com` you can use `relay.walletconnect.com` @@ -76,15 +75,15 @@ public final class RelayClient { logger: logger, keyValueStorage: keyValueStorage) } - + public func connect() throws { try dispatcher.connect() } - + public func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws { try dispatcher.disconnect(closeCode: closeCode) } - + /// Completes when networking client sends a request, error if it fails on client side public func publish(topic: String, payload: String, prompt: Bool = false) async throws { let params = RelayJSONRPC.PublishParams(topic: topic, message: payload, ttl: defaultTtl, prompt: prompt) @@ -93,13 +92,13 @@ public final class RelayClient { let requestJson = try request.json() try await dispatcher.send(requestJson) } - + /// Completes with an acknowledgement from the relay network. @discardableResult public func publish( topic: String, payload: String, prompt: Bool = false, - onNetworkAcknowledge: @escaping ((Error?) -> ())) -> Int64 { + onNetworkAcknowledge: @escaping ((Error?) -> Void)) -> Int64 { let params = RelayJSONRPC.PublishParams(topic: topic, message: payload, ttl: defaultTtl, prompt: prompt) let request = JSONRPCRequest(method: RelayJSONRPC.Method.publish.rawValue, params: params) let requestJson = try! request.json() @@ -114,15 +113,15 @@ public final class RelayClient { } cancellable = requestAcknowledgePublisher .filter {$0.id == request.id} - .sink { (subscriptionResponse) in + .sink { (_) in cancellable?.cancel() onNetworkAcknowledge(nil) } return request.id } - + @available(*, renamed: "subscribe(topic:)") - public func subscribe(topic: String, completion: @escaping (Error?) -> ()) { + public func subscribe(topic: String, completion: @escaping (Error?) -> Void) { logger.debug("waku: Subscribing on Topic: \(topic)") let params = RelayJSONRPC.SubscribeParams(topic: topic) let request = JSONRPCRequest(method: RelayJSONRPC.Method.subscribe.rawValue, params: params) @@ -146,7 +145,7 @@ public final class RelayClient { } } } - + public func subscribe(topic: String) async throws { return try await withCheckedThrowingContinuation { continuation in subscribe(topic: topic) { error in @@ -158,9 +157,8 @@ public final class RelayClient { } } } - - - @discardableResult public func unsubscribe(topic: String, completion: @escaping ((Error?) -> ())) -> Int64? { + + @discardableResult public func unsubscribe(topic: String, completion: @escaping ((Error?) -> Void)) -> Int64? { guard let subscriptionId = subscriptions[topic] else { completion(RelyerError.subscriptionIdNotFound) return nil @@ -185,7 +183,7 @@ public final class RelayClient { } cancellable = requestAcknowledgePublisher .filter {$0.id == request.id} - .sink { (subscriptionResponse) in + .sink { (_) in cancellable?.cancel() completion(nil) } @@ -200,7 +198,7 @@ public final class RelayClient { self.socketConnectionStatusPublisherSubject.send(.connected) } } - + private func handlePayloadMessage(_ payload: String) { if let request = tryDecode(SubscriptionRequest.self, from: payload), request.method == RelayJSONRPC.Method.subscription.rawValue { @@ -221,7 +219,7 @@ public final class RelayClient { logger.error("Unexpected response from network") } } - + private func tryDecode(_ type: T.Type, from payload: String) -> T? { if let data = payload.data(using: .utf8), let response = try? JSONDecoder().decode(T.self, from: data) { @@ -230,7 +228,7 @@ public final class RelayClient { return nil } } - + private func acknowledgeSubscription(requestId: Int64) { let response = JSONRPCResponse(id: requestId, result: AnyCodable(true)) let responseJson = try! response.json() @@ -241,7 +239,7 @@ public final class RelayClient { } } } - + static func makeRelayUrl(host: String, projectId: String) -> URL { var components = URLComponents() components.scheme = "wss" diff --git a/Sources/WalletConnectRelay/RelayJSONRPC.swift b/Sources/WalletConnectRelay/RelayJSONRPC.swift index e55ed5994..caac3ef03 100644 --- a/Sources/WalletConnectRelay/RelayJSONRPC.swift +++ b/Sources/WalletConnectRelay/RelayJSONRPC.swift @@ -9,28 +9,28 @@ enum RelayJSONRPC { case subscription = "waku_subscription" case unsubscribe = "waku_unsubscribe" } - + struct PublishParams: Codable, Equatable { let topic: String let message: String let ttl: Int let prompt: Bool? } - + struct SubscribeParams: Codable, Equatable { let topic: String } - + struct SubscriptionData: Codable, Equatable { let topic: String let message: String } - + struct SubscriptionParams: Codable, Equatable { let id: String let data: SubscriptionData } - + struct UnsubscribeParams: Codable, Equatable { let id: String let topic: String diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/AutomaticSocketConnectionHandler.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/AutomaticSocketConnectionHandler.swift index 48a32d851..1eb82b59a 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/AutomaticSocketConnectionHandler.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/AutomaticSocketConnectionHandler.swift @@ -1,4 +1,3 @@ - #if os(iOS) import UIKit #endif @@ -26,42 +25,42 @@ class AutomaticSocketConnectionHandler: SocketConnectionHandler { setUpNetworkMonitoring() socket.connect() } - + private func setUpStateObserving() { appStateObserver.onWillEnterBackground = { [unowned self] in registerBackgroundTask() } - + appStateObserver.onWillEnterForeground = { [unowned self] in socket.connect() } } - + private func setUpNetworkMonitoring() { networkMonitor.onSatisfied = { [weak self] in self?.handleNetworkSatisfied() } networkMonitor.startMonitoring() } - + func registerBackgroundTask() { backgroundTaskRegistrar.register(name: "Finish Network Tasks") { [unowned self] in endBackgroundTask() } } - + func endBackgroundTask() { socket.disconnect() } - + func handleConnect() throws { throw Error.manualSocketConnectionForbidden } - + func handleDisconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws { throw Error.manualSocketDisconnectionForbidden } - + func handleNetworkSatisfied() { if !socket.isConnected { socket.connect() diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/BackgroundTaskRegistering.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/BackgroundTaskRegistering.swift index f36d54e01..836283339 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/BackgroundTaskRegistering.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/BackgroundTaskRegistering.swift @@ -1,11 +1,10 @@ - import Foundation #if os(iOS) import UIKit #endif protocol BackgroundTaskRegistering { - func register(name: String, completion: @escaping ()->()) + func register(name: String, completion: @escaping () -> Void) } class BackgroundTaskRegistrar: BackgroundTaskRegistering { @@ -13,10 +12,10 @@ class BackgroundTaskRegistrar: BackgroundTaskRegistering { private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid #endif - func register(name: String, completion: @escaping () -> ()) { + func register(name: String, completion: @escaping () -> Void) { #if os(iOS) backgroundTaskID = .invalid - backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: name) { [unowned self] in + backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: name) { [unowned self] in UIApplication.shared.endBackgroundTask(backgroundTaskID) backgroundTaskID = .invalid completion() diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/ManualSocketConnectionHandler.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/ManualSocketConnectionHandler.swift index 9e756af45..ccd3978b4 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/ManualSocketConnectionHandler.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/ManualSocketConnectionHandler.swift @@ -1,10 +1,9 @@ - import Starscream import Foundation class ManualSocketConnectionHandler: SocketConnectionHandler { var socket: WebSocketConnecting - + init(socket: WebSocketConnecting) { self.socket = socket } @@ -12,7 +11,7 @@ class ManualSocketConnectionHandler: SocketConnectionHandler { func handleConnect() throws { socket.connect() } - + func handleDisconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws { socket.disconnect() } diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionHandler.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionHandler.swift index 4320b699e..dad34f1cd 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionHandler.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionHandler.swift @@ -1,4 +1,3 @@ - import Foundation protocol SocketConnectionHandler { diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionType.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionType.swift index bab534860..ce07f4c90 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionType.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/SocketConnectionType.swift @@ -1,4 +1,3 @@ - import Foundation public enum SocketConnectionType { diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketConnecting.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketConnecting.swift index 7a02aebd7..3ab34e8d4 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketConnecting.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketConnecting.swift @@ -1,7 +1,7 @@ import Starscream import Foundation -extension WebSocket: WebSocketConnecting{} +extension WebSocket: WebSocketConnecting {} protocol WebSocketConnecting { var isConnected: Bool {get} diff --git a/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketProtocol.swift b/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketProtocol.swift index d7e5a198e..3c03a2c83 100644 --- a/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketProtocol.swift +++ b/Sources/WalletConnectRelay/SocketConnectionHandler/WebSocketProtocol.swift @@ -1,12 +1,11 @@ - import Starscream -extension WebSocket: WebSocketProtocol{} +extension WebSocket: WebSocketProtocol {} protocol WebSocketProtocol { var isConnected: Bool {get} - var onConnect: (() -> ())? { get set } - var onDisconnect: ((Error?) -> ())? { get set } - var onText: ((String)->())? { get set } - func write(string: String, completion: (() -> ())?) + var onConnect: (() -> Void)? { get set } + var onDisconnect: ((Error?) -> Void)? { get set } + var onText: ((String) -> Void)? { get set } + func write(string: String, completion: (() -> Void)?) } diff --git a/Sources/WalletConnectSign/Constants/Time.swift b/Sources/WalletConnectSign/Constants/Time.swift index a84e7c770..cd1171cd1 100644 --- a/Sources/WalletConnectSign/Constants/Time.swift +++ b/Sources/WalletConnectSign/Constants/Time.swift @@ -3,13 +3,13 @@ import Foundation enum Time { - + static let hour = 3600 - + static var day: Int { hour * 24 } - + static var minute: Int { 60 } diff --git a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift index 87a976db2..265527564 100644 --- a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift @@ -16,9 +16,9 @@ final class ApproveEngine { var onSessionProposal: ((Session.Proposal) -> Void)? var onSessionRejected: ((Session.Proposal, SessionType.Reason) -> Void)? var onSessionSettle: ((Session) -> Void)? - + var settlingProposal: SessionProposal? - + private let networkingInteractor: NetworkInteracting private let pairingStore: WCPairingStorage private let sessionStore: WCSessionStorage @@ -27,7 +27,7 @@ final class ApproveEngine { private let metadata: AppMetadata private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging - + private var publishers = Set() init( @@ -48,10 +48,10 @@ final class ApproveEngine { self.logger = logger self.pairingStore = pairingStore self.sessionStore = sessionStore - + setupNetworkingSubscriptions() } - + func approveProposal(proposerPubKey: String, validating sessionNamespaces: [String: SessionNamespace]) async throws { let payload = try proposalPayloadsStore.get(key: proposerPubKey) @@ -60,10 +60,10 @@ final class ApproveEngine { } proposalPayloadsStore.delete(forKey: proposerPubKey) - + try Namespace.validate(sessionNamespaces) try Namespace.validateApproved(sessionNamespaces, against: proposal.requiredNamespaces) - + let selfPublicKey = try kms.createX25519KeyPair() guard let agreementKey = try? kms.performKeyAgreement( @@ -81,11 +81,11 @@ final class ApproveEngine { let proposeResponse = SessionType.ProposeResponse(relay: relay, responderPublicKey: selfPublicKey.hexRepresentation) let response = JSONRPCResponse(id: payload.wcRequest.id, result: AnyCodable(proposeResponse)) - + try await networkingInteractor.respond(topic: payload.topic, response: .response(response)) try await settle(topic: sessionTopic, proposal: proposal, namespaces: sessionNamespaces) } - + func reject(proposerPubKey: String, reason: ReasonCode) async throws { guard let payload = try proposalPayloadsStore.get(key: proposerPubKey) else { throw Errors.proposalPayloadsNotFound @@ -94,7 +94,7 @@ final class ApproveEngine { try await networkingInteractor.respondError(payload: payload, reason: reason) // TODO: Delete pairing if inactive } - + func settle(topic: String, proposal: SessionProposal, namespaces: [String: SessionNamespace]) async throws { guard let agreementKeys = try kms.getAgreementSecret(for: topic) else { throw Errors.agreementMissingOrInvalid @@ -111,7 +111,7 @@ final class ApproveEngine { let expiry = Date() .addingTimeInterval(TimeInterval(WCSession.defaultTimeToLive)) .timeIntervalSince1970 - + let settleParams = SessionType.SettleParams( relay: relay, controller: selfParticipant, @@ -138,7 +138,7 @@ final class ApproveEngine { // MARK: - Privates private extension ApproveEngine { - + func setupNetworkingSubscriptions() { networkingInteractor.responsePublisher .sink { [unowned self] response in @@ -151,7 +151,7 @@ private extension ApproveEngine { break } }.store(in: &publishers) - + networkingInteractor.wcRequestPublisher .sink { [unowned self] subscriptionPayload in do { @@ -169,7 +169,7 @@ private extension ApproveEngine { } }.store(in: &publishers) } - + func respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) { Task { do { @@ -179,13 +179,13 @@ private extension ApproveEngine { } } } - + func updatePairingMetadata(topic: String, metadata: AppMetadata) { guard var pairing = pairingStore.getPairing(forTopic: topic) else { return } pairing.peerMetadata = metadata pairingStore.setPairing(pairing) } - + // MARK: SessionProposeResponse // TODO: Move to Non-Controller SettleEngine func handleSessionProposeResponse(response: WCResponse, proposal: SessionType.ProposeParams) { @@ -200,15 +200,14 @@ private extension ApproveEngine { Task(priority: .background) { try? await networkingInteractor.subscribe(topic: sessionTopic) } - } - catch { + } catch { guard let error = error as? JSONRPCErrorResponse else { return logger.debug(error.localizedDescription) } onSessionRejected?(proposal.publicRepresentation(), SessionType.Reason(code: error.error.code, message: error.error.message)) } } - + func handleProposeResponse(pairingTopic: String, proposal: SessionProposal, result: JsonRpcResult) throws -> String { guard var pairing = pairingStore.getPairing(forTopic: pairingTopic) else { throw Errors.pairingNotFound } @@ -221,19 +220,19 @@ private extension ApproveEngine { } else { try pairing.updateExpiry() } - + pairingStore.setPairing(pairing) - + let selfPublicKey = try AgreementPublicKey(hex: proposal.proposer.publicKey) let proposeResponse = try response.result.get(SessionType.ProposeResponse.self) let agreementKeys = try kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposeResponse.responderPublicKey) let sessionTopic = agreementKeys.derivedTopic() logger.debug("Received Session Proposal response") - + try kms.setAgreementSecret(agreementKeys, topic: sessionTopic) sessionToPairingTopic.set(pairingTopic, forKey: sessionTopic) - + return sessionTopic case .error(let error): @@ -247,9 +246,9 @@ private extension ApproveEngine { throw error } } - + // MARK: SessionSettleResponse - + func handleSessionSettleResponse(response: WCResponse) { guard let session = sessionStore.getSession(forTopic: response.topic) else { return } switch response.result { @@ -266,36 +265,34 @@ private extension ApproveEngine { kms.deletePrivateKey(for: session.publicKey!) } } - + // MARK: SessionProposeRequest - + func handleSessionProposeRequest(payload: WCRequestSubscriptionPayload, proposal: SessionType.ProposeParams) throws { logger.debug("Received Session Proposal") - do { try Namespace.validate(proposal.requiredNamespaces) } - catch { throw Errors.respondError(payload: payload, reason: .invalidUpdateNamespaceRequest) } + do { try Namespace.validate(proposal.requiredNamespaces) } catch { throw Errors.respondError(payload: payload, reason: .invalidUpdateNamespaceRequest) } proposalPayloadsStore.set(payload, forKey: proposal.proposer.publicKey) onSessionProposal?(proposal.publicRepresentation()) } - + // MARK: SessionSettleRequest func handleSessionSettleRequest(payload: WCRequestSubscriptionPayload, settleParams: SessionType.SettleParams) throws { logger.debug("Did receive session settle request") - + guard let proposedNamespaces = settlingProposal?.requiredNamespaces else { throw Errors.respondError(payload: payload, reason: .invalidUpdateNamespaceRequest) } - + settlingProposal = nil - + let sessionNamespaces = settleParams.namespaces - + do { try Namespace.validate(sessionNamespaces) try Namespace.validateApproved(sessionNamespaces, against: proposedNamespaces) - } - catch WalletConnectError.unsupportedNamespace(let reason) { + } catch WalletConnectError.unsupportedNamespace(let reason) { throw Errors.respondError(payload: payload, reason: reason) } - + let topic = payload.topic let agreementKeys = try kms.getAgreementSecret(for: topic)! let selfParticipant = Participant( @@ -305,7 +302,7 @@ private extension ApproveEngine { if let pairingTopic = try? sessionToPairingTopic.get(key: topic) { updatePairingMetadata(topic: pairingTopic, metadata: settleParams.controller.metadata) } - + let session = WCSession( topic: topic, selfParticipant: selfParticipant, diff --git a/Sources/WalletConnectSign/Engine/Common/PairingEngine.swift b/Sources/WalletConnectSign/Engine/Common/PairingEngine.swift index 1ea9359dd..7b2231c82 100644 --- a/Sources/WalletConnectSign/Engine/Common/PairingEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/PairingEngine.swift @@ -4,7 +4,7 @@ import WalletConnectUtils import WalletConnectKMS final class PairingEngine { - + private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let pairingStore: WCPairingStorage @@ -30,23 +30,23 @@ final class PairingEngine { setupNetworkingSubscriptions() setupExpirationHandling() } - + func hasPairing(for topic: String) -> Bool { return pairingStore.hasPairing(forTopic: topic) } - + func getSettledPairing(for topic: String) -> WCPairing? { guard let pairing = pairingStore.getPairing(forTopic: topic) else { return nil } return pairing } - + func getSettledPairings() -> [Pairing] { pairingStore.getAll() .map {Pairing(topic: $0.topic, peer: $0.peerMetadata, expiryDate: $0.expiryDate)} } - + func create() async throws -> WalletConnectURI { let topic = topicInitializer() try await networkingInteractor.subscribe(topic: topic) @@ -56,7 +56,7 @@ final class PairingEngine { pairingStore.setPairing(pairing) return uri } - + func propose(pairingTopic: String, namespaces: [String: ProposalNamespace], relay: RelayProtocolOptions) async throws { logger.debug("Propose Session on topic: \(pairingTopic)") try Namespace.validate(namespaces) @@ -79,14 +79,14 @@ final class PairingEngine { } } - func ping(topic: String, completion: @escaping ((Result) -> ())) { + func ping(topic: String, completion: @escaping ((Result) -> Void)) { guard pairingStore.hasPairing(forTopic: topic) else { logger.debug("Could not find pairing to ping for topic \(topic)") return } networkingInteractor.requestPeerResponse(.wcPairingPing, onTopic: topic) { [unowned self] result in switch result { - case .success(_): + case .success: logger.debug("Did receive ping response") completion(.success(())) case .failure(let error): @@ -99,30 +99,30 @@ final class PairingEngine { // MARK: Private private extension PairingEngine { - + func setupNetworkingSubscriptions() { networkingInteractor.transportConnectionPublisher .sink { [unowned self] (_) in let topics = pairingStore.getAll() - .map{$0.topic} - topics.forEach{ topic in Task{try? await networkingInteractor.subscribe(topic: topic)}} + .map {$0.topic} + topics.forEach { topic in Task {try? await networkingInteractor.subscribe(topic: topic)}} }.store(in: &publishers) - + networkingInteractor.wcRequestPublisher .sink { [unowned self] subscriptionPayload in switch subscriptionPayload.wcRequest.params { - case .pairingPing(_): + case .pairingPing: wcPairingPing(subscriptionPayload) default: return } }.store(in: &publishers) } - + func wcPairingPing(_ payload: WCRequestSubscriptionPayload) { networkingInteractor.respondSuccess(for: payload) } - + func setupExpirationHandling() { pairingStore.onPairingExpiration = { [weak self] pairing in self?.kms.deleteSymmetricKey(for: pairing.topic) diff --git a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift index d033a97ef..a64ceadc3 100644 --- a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift @@ -14,7 +14,7 @@ final class SessionEngine { var onSessionRejected: ((String, SessionType.Reason) -> Void)? var onSessionDelete: ((String, SessionType.Reason) -> Void)? var onEventReceived: ((String, Session.Event, Blockchain?) -> Void)? - + private let sessionStore: WCSessionStorage private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol @@ -31,26 +31,26 @@ final class SessionEngine { self.kms = kms self.sessionStore = sessionStore self.logger = logger - + setupNetworkingSubscriptions() setupExpirationSubscriptions() } - + func hasSession(for topic: String) -> Bool { return sessionStore.hasSession(forTopic: topic) } - + func getSessions() -> [Session] { - sessionStore.getAll().map{$0.publicRepresentation()} + sessionStore.getAll().map {$0.publicRepresentation()} } - + func delete(topic: String, reason: Reason) async throws { logger.debug("Will delete session for reason: message: \(reason.message) code: \(reason.code)") try await networkingInteractor.request(.wcSessionDelete(reason.internalRepresentation()), onTopic: topic) sessionStore.delete(topic: topic) networkingInteractor.unsubscribe(topic: topic) } - + func ping(topic: String, completion: @escaping (Result) -> Void) { guard sessionStore.hasSession(forTopic: topic) else { logger.debug("Could not find session to ping for topic \(topic)") @@ -58,7 +58,7 @@ final class SessionEngine { } networkingInteractor.requestPeerResponse(.wcSessionPing, onTopic: topic) { [unowned self] result in switch result { - case .success(_): + case .success: logger.debug("Did receive ping response") completion(.success(())) case .failure(let error): @@ -66,7 +66,7 @@ final class SessionEngine { } } } - + func request(_ request: Request) async throws { print("will request on session topic: \(request.topic)") guard let session = sessionStore.getSession(forTopic: request.topic), session.acknowledged else { @@ -80,14 +80,14 @@ final class SessionEngine { let sessionRequestParams = SessionType.RequestParams(request: chainRequest, chainId: request.chainId) try await networkingInteractor.request(.wcSessionRequest(sessionRequestParams), onTopic: request.topic) } - + func respondSessionRequest(topic: String, response: JsonRpcResult) async throws { guard sessionStore.hasSession(forTopic: topic) else { throw Errors.sessionNotFound(topic: topic) } try await networkingInteractor.respond(topic: topic, response: response) } - + func emit(topic: String, event: SessionType.EventParams.Event, chainId: Blockchain) async throws { guard let session = sessionStore.getSession(forTopic: topic) else { logger.debug("Could not find session for topic \(topic)") @@ -101,19 +101,19 @@ final class SessionEngine { } } -//MARK: - Privates +// MARK: - Privates private extension SessionEngine { - + func setupNetworkingSubscriptions() { - networkingInteractor.wcRequestPublisher.sink { [unowned self] subscriptionPayload in + networkingInteractor.wcRequestPublisher.sink { [unowned self] subscriptionPayload in do { switch subscriptionPayload.wcRequest.params { case .sessionDelete(let deleteParams): try onSessionDelete(subscriptionPayload, deleteParams: deleteParams) case .sessionRequest(let sessionRequestParams): try onSessionRequest(subscriptionPayload, payloadParams: sessionRequestParams) - case .sessionPing(_): + case .sessionPing: onSessionPing(subscriptionPayload) case .sessionEvent(let eventParams): try onSessionEvent(subscriptionPayload, eventParams: eventParams) @@ -125,19 +125,19 @@ private extension SessionEngine { logger.error("Unexpected Error: \(error.localizedDescription)") } }.store(in: &publishers) - + networkingInteractor.transportConnectionPublisher .sink { [unowned self] (_) in - let topics = sessionStore.getAll().map{$0.topic} - topics.forEach{ topic in Task { try? await networkingInteractor.subscribe(topic: topic) } } + let topics = sessionStore.getAll().map {$0.topic} + topics.forEach { topic in Task { try? await networkingInteractor.subscribe(topic: topic) } } }.store(in: &publishers) - + networkingInteractor.responsePublisher .sink { [unowned self] response in self.handleResponse(response) }.store(in: &publishers) } - + func respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) { Task { do { @@ -147,7 +147,7 @@ private extension SessionEngine { } } } - + func onSessionDelete(_ payload: WCRequestSubscriptionPayload, deleteParams: SessionType.DeleteParams) throws { let topic = payload.topic guard sessionStore.hasSession(forTopic: topic) else { @@ -158,7 +158,7 @@ private extension SessionEngine { networkingInteractor.respondSuccess(for: payload) onSessionDelete?(topic, deleteParams) } - + func onSessionRequest(_ payload: WCRequestSubscriptionPayload, payloadParams: SessionType.RequestParams) throws { let topic = payload.topic let jsonRpcRequest = JSONRPCRequest(id: payload.wcRequest.id, method: payloadParams.request.method, params: payloadParams.request.params) @@ -168,7 +168,7 @@ private extension SessionEngine { method: jsonRpcRequest.method, params: jsonRpcRequest.params, chainId: payloadParams.chainId) - + guard let session = sessionStore.getSession(forTopic: topic) else { throw Errors.respondError(payload: payload, reason: .noContextWithTopic(context: .session, topic: topic)) } @@ -181,11 +181,11 @@ private extension SessionEngine { } onSessionRequest?(request) } - + func onSessionPing(_ payload: WCRequestSubscriptionPayload) { networkingInteractor.respondSuccess(for: payload) } - + func onSessionEvent(_ payload: WCRequestSubscriptionPayload, eventParams: SessionType.EventParams) throws { let event = eventParams.event let topic = payload.topic diff --git a/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift b/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift index 3f3755543..07f4106cf 100644 --- a/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift +++ b/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils import WalletConnectKMS @@ -6,8 +5,8 @@ import Combine final class ControllerSessionStateMachine { - var onNamespacesUpdate: ((String, [String: SessionNamespace])->())? - var onExtend: ((String, Date)->())? + var onNamespacesUpdate: ((String, [String: SessionNamespace]) -> Void)? + var onExtend: ((String, Date) -> Void)? private let sessionStore: WCSessionStorage private let networkingInteractor: NetworkInteracting @@ -27,7 +26,7 @@ final class ControllerSessionStateMachine { handleResponse(response) }.store(in: &publishers) } - + func update(topic: String, namespaces: [String: SessionNamespace]) async throws { var session = try getSession(for: topic) try validateControlledAcknowledged(session) @@ -37,7 +36,7 @@ final class ControllerSessionStateMachine { sessionStore.setSession(session) try await networkingInteractor.request(.wcSessionUpdate(SessionType.UpdateParams(namespaces: namespaces)), onTopic: topic) } - + func extend(topic: String, by ttl: Int64) async throws { var session = try getSession(for: topic) try validateControlledAcknowledged(session) @@ -46,9 +45,9 @@ final class ControllerSessionStateMachine { sessionStore.setSession(session) try await networkingInteractor.request(.wcSessionExtend(SessionType.UpdateExpiryParams(expiry: newExpiry)), onTopic: topic) } - + // MARK: - Handle Response - + private func handleResponse(_ response: WCResponse) { switch response.requestParams { case .sessionUpdate: @@ -59,7 +58,7 @@ final class ControllerSessionStateMachine { break } } - + // TODO: Re-enable callback private func handleUpdateResponse(topic: String, result: JsonRpcResult) { guard let _ = sessionStore.getSession(forTopic: topic) else { @@ -67,29 +66,29 @@ final class ControllerSessionStateMachine { } switch result { case .response: - //TODO - state sync + // TODO - state sync // onNamespacesUpdate?(session.topic, session.namespaces) break case .error: - //TODO - state sync + // TODO - state sync logger.error("Peer failed to update methods.") } } - + private func handleUpdateExpiryResponse(topic: String, result: JsonRpcResult) { guard let session = sessionStore.getSession(forTopic: topic) else { return } switch result { case .response: - //TODO - state sync + // TODO - state sync onExtend?(session.topic, session.expiryDate) case .error: - //TODO - state sync + // TODO - state sync logger.error("Peer failed to update events.") } } - + // MARK: - Private private func getSession(for topic: String) throws -> WCSession { if let session = sessionStore.getSession(forTopic: topic) { @@ -98,7 +97,7 @@ final class ControllerSessionStateMachine { throw WalletConnectError.noSessionMatchingTopic(topic) } } - + private func validateControlledAcknowledged(_ session: WCSession) throws { guard session.acknowledged else { throw WalletConnectError.sessionNotAcknowledged(session.topic) diff --git a/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift b/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift index 73d45b4de..72ed7c00a 100644 --- a/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift +++ b/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectKMS @@ -6,7 +5,7 @@ actor PairEngine { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let pairingStore: WCPairingStorage - + init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, pairingStore: WCPairingStorage) { @@ -14,7 +13,7 @@ actor PairEngine { self.kms = kms self.pairingStore = pairingStore } - + func pair(_ uri: WalletConnectURI) async throws { guard !hasPairing(for: uri.topic) else { throw WalletConnectError.pairingAlreadyExist @@ -26,7 +25,7 @@ actor PairEngine { pairing.activate() pairingStore.setPairing(pairing) } - + func hasPairing(for topic: String) -> Bool { return pairingStore.hasPairing(forTopic: topic) } diff --git a/Sources/WalletConnectSign/Engine/NonController/NonControllerSessionStateMachine.swift b/Sources/WalletConnectSign/Engine/NonController/NonControllerSessionStateMachine.swift index 63a2bc443..683b95573 100644 --- a/Sources/WalletConnectSign/Engine/NonController/NonControllerSessionStateMachine.swift +++ b/Sources/WalletConnectSign/Engine/NonController/NonControllerSessionStateMachine.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils import WalletConnectKMS @@ -9,8 +8,8 @@ final class NonControllerSessionStateMachine { case respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) } - var onNamespacesUpdate: ((String, [String: SessionNamespace])->())? - var onExtend: ((String, Date) -> ())? + var onNamespacesUpdate: ((String, [String: SessionNamespace]) -> Void)? + var onExtend: ((String, Date) -> Void)? private let sessionStore: WCSessionStorage private let networkingInteractor: NetworkInteracting @@ -28,7 +27,7 @@ final class NonControllerSessionStateMachine { self.logger = logger setUpWCRequestHandling() } - + private func setUpWCRequestHandling() { networkingInteractor.wcRequestPublisher .sink { [unowned self] subscriptionPayload in @@ -47,7 +46,7 @@ final class NonControllerSessionStateMachine { } }.store(in: &publishers) } - + private func respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) { Task { do { @@ -57,7 +56,7 @@ final class NonControllerSessionStateMachine { } } } - + // TODO: Update stored session namespaces private func onSessionUpdateNamespacesRequest(payload: WCRequestSubscriptionPayload, updateParams: SessionType.UpdateParams) throws { do { diff --git a/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcHistory.swift b/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcHistory.swift index 2f6ab3389..321bb5a62 100644 --- a/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcHistory.swift +++ b/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcHistory.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils @@ -9,20 +8,20 @@ protocol JsonRpcHistoryRecording { func resolve(response: JsonRpcResult) throws -> JsonRpcRecord func exist(id: Int64) -> Bool } -//TODO -remove and use jsonrpc history only from utils +// TODO -remove and use jsonrpc history only from utils class JsonRpcHistory: JsonRpcHistoryRecording { let storage: CodableStore let logger: ConsoleLogging - + init(logger: ConsoleLogging, keyValueStore: CodableStore) { self.logger = logger self.storage = keyValueStore } - + func get(id: Int64) -> JsonRpcRecord? { try? storage.get(key: "\(id)") } - + func set(topic: String, request: WCRequest, chainId: String? = nil) throws { guard !exist(id: request.id) else { throw WalletConnectError.internal(.jsonRpcDuplicateDetected) @@ -31,7 +30,7 @@ class JsonRpcHistory: JsonRpcHistoryRecording { let record = JsonRpcRecord(id: request.id, topic: topic, request: JsonRpcRecord.Request(method: request.method, params: request.params), response: nil, chainId: chainId) storage.set(record, forKey: "\(request.id)") } - + func delete(topic: String) { storage.getAll().forEach { record in if record.topic == topic { @@ -39,7 +38,7 @@ class JsonRpcHistory: JsonRpcHistoryRecording { } } } - + func resolve(response: JsonRpcResult) throws -> JsonRpcRecord { logger.debug("Resolving JSON-RPC response - ID: \(response.id)") guard var record = try? storage.get(key: "\(response.id)") else { @@ -53,12 +52,12 @@ class JsonRpcHistory: JsonRpcHistoryRecording { return record } } - + func exist(id: Int64) -> Bool { return (try? storage.get(key: "\(id)")) != nil } - + public func getPending() -> [JsonRpcRecord] { - storage.getAll().filter{$0.response == nil} + storage.getAll().filter {$0.response == nil} } } diff --git a/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcRecord.swift b/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcRecord.swift index da8a1e0b1..edfb14dc8 100644 --- a/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcRecord.swift +++ b/Sources/WalletConnectSign/JsonRpcHistory/JsonRpcRecord.swift @@ -1,5 +1,3 @@ - - import Foundation import WalletConnectUtils @@ -15,4 +13,3 @@ struct JsonRpcRecord: Codable { let params: WCRequest.Params } } - diff --git a/Sources/WalletConnectSign/Namespace.swift b/Sources/WalletConnectSign/Namespace.swift index 0a4f52f04..3425d6e3a 100644 --- a/Sources/WalletConnectSign/Namespace.swift +++ b/Sources/WalletConnectSign/Namespace.swift @@ -1,24 +1,24 @@ import WalletConnectUtils public struct ProposalNamespace: Equatable, Codable { - + public let chains: Set public let methods: Set public let events: Set public let extensions: [Extension]? - + public struct Extension: Equatable, Codable { public let chains: Set public let methods: Set public let events: Set - + public init(chains: Set, methods: Set, events: Set) { self.chains = chains self.methods = methods self.events = events } } - + public init(chains: Set, methods: Set, events: Set, extensions: [ProposalNamespace.Extension]? = nil) { self.chains = chains self.methods = methods @@ -28,24 +28,24 @@ public struct ProposalNamespace: Equatable, Codable { } public struct SessionNamespace: Equatable, Codable { - + public let accounts: Set public let methods: Set public let events: Set public let extensions: [Extension]? - + public struct Extension: Equatable, Codable { public let accounts: Set public let methods: Set public let events: Set - + public init(accounts: Set, methods: Set, events: Set) { self.accounts = accounts self.methods = methods self.events = events } } - + public init(accounts: Set, methods: Set, events: Set, extensions: [SessionNamespace.Extension]? = nil) { self.accounts = accounts self.methods = methods @@ -55,7 +55,7 @@ public struct SessionNamespace: Equatable, Codable { } enum Namespace { - + static func validate(_ namespaces: [String: ProposalNamespace]) throws { for (key, namespace) in namespaces { if namespace.chains.isEmpty { @@ -75,7 +75,7 @@ enum Namespace { } } } - + static func validate(_ namespaces: [String: SessionNamespace]) throws { for (key, namespace) in namespaces { if namespace.accounts.isEmpty { @@ -95,7 +95,7 @@ enum Namespace { } } } - + static func validateApproved( _ sessionNamespaces: [String: SessionNamespace], against proposalNamespaces: [String: ProposalNamespace] diff --git a/Sources/WalletConnectSign/NetworkInteractor/NetworkInteractor.swift b/Sources/WalletConnectSign/NetworkInteractor/NetworkInteractor.swift index 5170b73f5..022e74a2c 100644 --- a/Sources/WalletConnectSign/NetworkInteractor/NetworkInteractor.swift +++ b/Sources/WalletConnectSign/NetworkInteractor/NetworkInteractor.swift @@ -1,4 +1,3 @@ - import Foundation import Combine import WalletConnectUtils @@ -19,9 +18,9 @@ protocol NetworkInteracting: AnyObject { /// Completes when request sent from a networking client func request(_ wcMethod: WCMethod, onTopic topic: String) async throws /// Completes with an acknowledgement from the relay network - func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> ())) + func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> Void)) /// Completes with a peer response - func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>)->())?) + func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>) -> Void)?) func respond(topic: String, response: JsonRpcResult) async throws func respondSuccess(payload: WCRequestSubscriptionPayload) async throws func respondSuccess(for payload: WCRequestSubscriptionPayload) @@ -39,15 +38,15 @@ extension NetworkInteracting { class NetworkInteractor: NetworkInteracting { private var publishers = [AnyCancellable]() - + private var relayClient: NetworkRelaying private let serializer: Serializing private let jsonRpcHistory: JsonRpcHistoryRecording - + private let transportConnectionPublisherSubject = PassthroughSubject() private let responsePublisherSubject = PassthroughSubject() private let wcRequestPublisherSubject = PassthroughSubject() - + var transportConnectionPublisher: AnyPublisher { transportConnectionPublisherSubject.eraseToAnyPublisher() } @@ -59,7 +58,7 @@ class NetworkInteractor: NetworkInteracting { } let logger: ConsoleLogging - + init(relayClient: NetworkRelaying, serializer: Serializing, logger: ConsoleLogging, @@ -70,11 +69,11 @@ class NetworkInteractor: NetworkInteracting { self.jsonRpcHistory = jsonRpcHistory setUpPublishers() } - + func request(_ wcMethod: WCMethod, onTopic topic: String) async throws { try await request(topic: topic, payload: wcMethod.asRequest()) } - + /// Completes when networking client sends a request func request(topic: String, payload: WCRequest) async throws { try jsonRpcHistory.set(topic: topic, request: payload, chainId: getChainId(payload)) @@ -83,7 +82,7 @@ class NetworkInteractor: NetworkInteracting { try await relayClient.publish(topic: topic, payload: message, prompt: prompt) } - func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>) -> ())?) { + func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>) -> Void)?) { let payload = wcMethod.asRequest() do { try jsonRpcHistory.set(topic: topic, request: payload, chainId: getChainId(payload)) @@ -116,10 +115,10 @@ class NetworkInteractor: NetworkInteracting { logger.error(error) } } - + /// Completes with an acknowledgement from the relay network. /// completes with error if networking client was not able to send a message - func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> ())) { + func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> Void)) { do { let payload = wcMethod.asRequest() try jsonRpcHistory.set(topic: topic, request: payload, chainId: getChainId(payload)) @@ -140,25 +139,24 @@ class NetworkInteractor: NetworkInteracting { let message = try serializer.serialize(topic: topic, encodable: response.value) logger.debug("Responding....topic: \(topic)") - + do { try await relayClient.publish(topic: topic, payload: message, prompt: false) - } - catch WalletConnectError.internal(.jsonRpcDuplicateDetected) { + } catch WalletConnectError.internal(.jsonRpcDuplicateDetected) { logger.info("Info: Json Rpc Duplicate Detected") } } - + func respondSuccess(payload: WCRequestSubscriptionPayload) async throws { let response = JSONRPCResponse(id: payload.wcRequest.id, result: AnyCodable(true)) try await respond(topic: payload.topic, response: JsonRpcResult.response(response)) } - + func respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) async throws { let response = JSONRPCErrorResponse(id: payload.wcRequest.id, error: JSONRPCErrorResponse.Error(code: reason.code, message: reason.message)) try await respond(topic: payload.topic, response: JsonRpcResult.error(response)) } - + // TODO: Move to async func respondSuccess(for payload: WCRequestSubscriptionPayload) { Task { @@ -168,9 +166,9 @@ class NetworkInteractor: NetworkInteracting { self.logger.error("Respond Success failed with: \(error.localizedDescription)") } } - + } - + func subscribe(topic: String) async throws { try await relayClient.subscribe(topic: topic) } @@ -184,7 +182,7 @@ class NetworkInteractor: NetworkInteracting { } } } - + // MARK: - Private private func setUpPublishers() { @@ -198,7 +196,7 @@ class NetworkInteractor: NetworkInteracting { manageSubscription(topic, message) } } - + private func manageSubscription(_ topic: String, _ message: String) { if let deserializedJsonRpcRequest: WCRequest = serializer.tryDeserialize(topic: topic, message: message) { handleWCRequest(topic: topic, request: deserializedJsonRpcRequest) @@ -210,7 +208,7 @@ class NetworkInteractor: NetworkInteracting { logger.warn("Warning: WalletConnect Relay - Received unknown object type from networking relay") } } - + private func handleWCRequest(topic: String, request: WCRequest) { do { try jsonRpcHistory.set(topic: topic, request: request, chainId: getChainId(request)) @@ -222,7 +220,7 @@ class NetworkInteractor: NetworkInteracting { logger.error(error) } } - + private func handleJsonRpcResponse(response: JSONRPCResponse) { do { let record = try jsonRpcHistory.resolve(response: JsonRpcResult.response(response)) @@ -233,11 +231,11 @@ class NetworkInteractor: NetworkInteracting { requestParams: record.request.params, result: JsonRpcResult.response(response)) responsePublisherSubject.send(wcResponse) - } catch { + } catch { logger.info("Info: \(error.localizedDescription)") } } - + private func handleJsonRpcErrorResponse(response: JSONRPCErrorResponse) { do { let record = try jsonRpcHistory.resolve(response: JsonRpcResult.error(response)) @@ -252,7 +250,7 @@ class NetworkInteractor: NetworkInteracting { logger.info("Info: \(error.localizedDescription)") } } - + private func shouldPrompt(_ method: WCRequest.Method) -> Bool { switch method { case .sessionRequest: @@ -261,7 +259,7 @@ class NetworkInteractor: NetworkInteracting { return false } } - + func getChainId(_ request: WCRequest) -> String? { guard case let .sessionRequest(payload) = request.params else {return nil} return payload.chainId.absoluteString diff --git a/Sources/WalletConnectSign/NetworkInteractor/NetworkRelaying.swift b/Sources/WalletConnectSign/NetworkInteractor/NetworkRelaying.swift index d5cd126f2..a6a948b22 100644 --- a/Sources/WalletConnectSign/NetworkInteractor/NetworkRelaying.swift +++ b/Sources/WalletConnectSign/NetworkInteractor/NetworkRelaying.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectRelay import Combine @@ -6,15 +5,15 @@ import Combine extension RelayClient: NetworkRelaying {} protocol NetworkRelaying { - var onMessage: ((_ topic: String, _ message: String) -> ())? {get set} + var onMessage: ((_ topic: String, _ message: String) -> Void)? {get set} var socketConnectionStatusPublisher: AnyPublisher { get } func connect() throws func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws func publish(topic: String, payload: String, prompt: Bool) async throws /// - returns: request id - @discardableResult func publish(topic: String, payload: String, prompt: Bool, onNetworkAcknowledge: @escaping ((Error?)->())) -> Int64 - func subscribe(topic: String, completion: @escaping (Error?)->()) - func subscribe(topic: String) async throws + @discardableResult func publish(topic: String, payload: String, prompt: Bool, onNetworkAcknowledge: @escaping ((Error?) -> Void)) -> Int64 + func subscribe(topic: String, completion: @escaping (Error?) -> Void) + func subscribe(topic: String) async throws /// - returns: request id - @discardableResult func unsubscribe(topic: String, completion: @escaping ((Error?)->())) -> Int64? + @discardableResult func unsubscribe(topic: String, completion: @escaping ((Error?) -> Void)) -> Int64? } diff --git a/Sources/WalletConnectSign/Reason.swift b/Sources/WalletConnectSign/Reason.swift index 8c77e1c03..d49aab825 100644 --- a/Sources/WalletConnectSign/Reason.swift +++ b/Sources/WalletConnectSign/Reason.swift @@ -1,9 +1,9 @@ // TODO: Refactor into codes. Reference: https://docs.walletconnect.com/2.0/protocol/reason-codes public struct Reason { - + public let code: Int public let message: String - + public init(code: Int, message: String) { self.code = code self.message = message diff --git a/Sources/WalletConnectSign/RejectionReason.swift b/Sources/WalletConnectSign/RejectionReason.swift index f69ca95af..cee66c716 100644 --- a/Sources/WalletConnectSign/RejectionReason.swift +++ b/Sources/WalletConnectSign/RejectionReason.swift @@ -1,4 +1,3 @@ - import Foundation /// https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md diff --git a/Sources/WalletConnectSign/Request.swift b/Sources/WalletConnectSign/Request.swift index b9e7b07f0..0a3bebf78 100644 --- a/Sources/WalletConnectSign/Request.swift +++ b/Sources/WalletConnectSign/Request.swift @@ -7,7 +7,7 @@ public struct Request: Codable, Equatable { public let method: String public let params: AnyCodable public let chainId: Blockchain - + internal init(id: Int64, topic: String, method: String, params: AnyCodable, chainId: Blockchain) { self.id = id self.topic = topic @@ -15,7 +15,7 @@ public struct Request: Codable, Equatable { self.params = params self.chainId = chainId } - + public init(topic: String, method: String, params: AnyCodable, chainId: Blockchain) { self.id = Self.generateId() self.topic = topic @@ -23,7 +23,7 @@ public struct Request: Codable, Equatable { self.params = params self.chainId = chainId } - + public static func generateId() -> Int64 { return Int64(Date().timeIntervalSince1970 * 1000)*1000 + Int64.random(in: 0..<1000) } diff --git a/Sources/WalletConnectSign/Response.swift b/Sources/WalletConnectSign/Response.swift index 736893173..8dd4a0f0f 100644 --- a/Sources/WalletConnectSign/Response.swift +++ b/Sources/WalletConnectSign/Response.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils diff --git a/Sources/WalletConnectSign/Serializing.swift b/Sources/WalletConnectSign/Serializing.swift index abcf159b6..b3af40940 100644 --- a/Sources/WalletConnectSign/Serializing.swift +++ b/Sources/WalletConnectSign/Serializing.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectKMS diff --git a/Sources/WalletConnectSign/Services/CelanupService.swift b/Sources/WalletConnectSign/Services/CelanupService.swift index 649aa343d..e0e083796 100644 --- a/Sources/WalletConnectSign/Services/CelanupService.swift +++ b/Sources/WalletConnectSign/Services/CelanupService.swift @@ -3,19 +3,19 @@ import WalletConnectKMS import WalletConnectUtils final class CleanupService { - + private let pairingStore: WCPairingStorage private let sessionStore: WCSessionStorage private let kms: KeyManagementServiceProtocol private let sessionToPairingTopic: CodableStore - + init(pairingStore: WCPairingStorage, sessionStore: WCSessionStorage, kms: KeyManagementServiceProtocol, sessionToPairingTopic: CodableStore) { self.pairingStore = pairingStore self.sessionStore = sessionStore self.sessionToPairingTopic = sessionToPairingTopic self.kms = kms } - + func cleanup() throws { pairingStore.deleteAll() sessionStore.deleteAll() diff --git a/Sources/WalletConnectSign/Session.swift b/Sources/WalletConnectSign/Session.swift index 48aec0338..f988f9825 100644 --- a/Sources/WalletConnectSign/Session.swift +++ b/Sources/WalletConnectSign/Session.swift @@ -15,12 +15,12 @@ public struct Session { } extension Session { - + public struct Proposal: Equatable { public var id: String public let proposer: AppMetadata public let requiredNamespaces: [String: ProposalNamespace] - + // TODO: Refactor internal objects to manage only needed data internal let proposal: SessionProposal } @@ -28,10 +28,10 @@ extension Session { public struct Event: Equatable, Hashable { public let name: String public let data: AnyCodable - - internal func internalRepresentation() -> SessionType.EventParams.Event{ + + internal func internalRepresentation() -> SessionType.EventParams.Event { SessionType.EventParams.Event(name: name, data: data) } } - + } diff --git a/Sources/WalletConnectSign/Sign/Sign.swift b/Sources/WalletConnectSign/Sign/Sign.swift index ce7fe2faf..8cd067080 100644 --- a/Sources/WalletConnectSign/Sign/Sign.swift +++ b/Sources/WalletConnectSign/Sign/Sign.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils import WalletConnectRelay @@ -9,11 +8,11 @@ public typealias Blockchain = WalletConnectUtils.Blockchain public class Sign { public static let instance = Sign() - + private static var config: Config? private let client: SignClient private let relayClient: RelayClient - + private init() { guard let config = Sign.config else { fatalError("Error - you must call configure(_:) before accessing the shared instance.") @@ -22,56 +21,56 @@ public class Sign { client = SignClient(metadata: config.metadata, relayClient: relayClient) client.delegate = self } - + static public func configure(_ config: Config) { Sign.config = config } - + var sessionProposalPublisherSubject = PassthroughSubject() public var sessionProposalPublisher: AnyPublisher { sessionProposalPublisherSubject.eraseToAnyPublisher() } - + var sessionRequestPublisherSubject = PassthroughSubject() public var sessionRequestPublisher: AnyPublisher { sessionRequestPublisherSubject.eraseToAnyPublisher() } - + var socketConnectionStatusPublisherSubject = PassthroughSubject() public var socketConnectionStatusPublisher: AnyPublisher { socketConnectionStatusPublisherSubject.eraseToAnyPublisher() } - + var sessionSettlePublisherSubject = PassthroughSubject() public var sessionSettlePublisher: AnyPublisher { sessionSettlePublisherSubject.eraseToAnyPublisher() } - + var sessionDeletePublisherSubject = PassthroughSubject<(String, Reason), Never>() public var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> { sessionDeletePublisherSubject.eraseToAnyPublisher() } - + var sessionResponsePublisherSubject = PassthroughSubject() public var sessionResponsePublisher: AnyPublisher { sessionResponsePublisherSubject.eraseToAnyPublisher() } - + var sessionRejectionPublisherSubject = PassthroughSubject<(Session.Proposal, Reason), Never>() public var sessionRejectionPublisher: AnyPublisher<(Session.Proposal, Reason), Never> { sessionRejectionPublisherSubject.eraseToAnyPublisher() } - - var sessionUpdatePublisherSubject = PassthroughSubject<(sessionTopic: String, namespaces: [String : SessionNamespace]), Never>() - public var sessionUpdatePublisher: AnyPublisher<(sessionTopic: String, namespaces: [String : SessionNamespace]), Never> { + + var sessionUpdatePublisherSubject = PassthroughSubject<(sessionTopic: String, namespaces: [String: SessionNamespace]), Never>() + public var sessionUpdatePublisher: AnyPublisher<(sessionTopic: String, namespaces: [String: SessionNamespace]), Never> { sessionUpdatePublisherSubject.eraseToAnyPublisher() } - + var sessionEventPublisherSubject = PassthroughSubject<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never>() public var sessionEventPublisher: AnyPublisher<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never> { sessionEventPublisherSubject.eraseToAnyPublisher() } - + var sessionExtendPublisherSubject = PassthroughSubject<(sessionTopic: String, date: Date), Never>() public var sessionExtendPublisher: AnyPublisher<(sessionTopic: String, date: Date), Never> { sessionExtendPublisherSubject.eraseToAnyPublisher() @@ -79,7 +78,7 @@ public class Sign { } extension Sign: SignClientDelegate { - + public func didReceive(sessionProposal: Session.Proposal) { sessionProposalPublisherSubject.send(sessionProposal) } @@ -87,48 +86,48 @@ extension Sign: SignClientDelegate { public func didReceive(sessionRequest: Request) { sessionRequestPublisherSubject.send(sessionRequest) } - + public func didReceive(sessionResponse: Response) { sessionResponsePublisherSubject.send(sessionResponse) } - + public func didDelete(sessionTopic: String, reason: Reason) { sessionDeletePublisherSubject.send((sessionTopic, reason)) } - - public func didUpdate(sessionTopic: String, namespaces: [String : SessionNamespace]) { + + public func didUpdate(sessionTopic: String, namespaces: [String: SessionNamespace]) { sessionUpdatePublisherSubject.send((sessionTopic, namespaces)) } - + public func didExtend(sessionTopic: String, to date: Date) { sessionExtendPublisherSubject.send((sessionTopic, date)) } - + public func didSettle(session: Session) { sessionSettlePublisherSubject.send(session) } - + public func didReceive(event: Session.Event, sessionTopic: String, chainId: Blockchain?) { sessionEventPublisherSubject.send((event, sessionTopic, chainId)) } - + public func didReject(proposal: Session.Proposal, reason: Reason) { sessionRejectionPublisherSubject.send((proposal, reason)) } - + public func didChangeSocketConnectionStatus(_ status: SocketConnectionStatus) { socketConnectionStatusPublisherSubject.send(status) } } extension Sign { - + /// For the Proposer to propose a session to a responder. /// Function will create pending pairing sequence or propose a session on existing pairing. When responder client approves pairing, session is be proposed automatically by your client. /// - Parameter sessionPermissions: The session permissions the responder will be requested for. /// - Parameter topic: Optional parameter - use it if you already have an established pairing with peer client. /// - Returns: Pairing URI that should be shared with responder out of bound. Common way is to present it as a QR code. Pairing URI will be nil if you are going to establish a session on existing Pairing and `topic` function parameter was provided. - public func connect(requiredNamespaces: [String : ProposalNamespace], topic: String? = nil) async throws -> String? { + public func connect(requiredNamespaces: [String: ProposalNamespace], topic: String? = nil) async throws -> String? { try await client.connect(requiredNamespaces: requiredNamespaces, topic: topic) } @@ -149,7 +148,7 @@ extension Sign { /// - accounts: A Set of accounts that the dapp will be allowed to request methods executions on. /// - methods: A Set of methods that the dapp will be allowed to request. /// - events: A Set of events - public func approve(proposalId: String, namespaces: [String : SessionNamespace]) async throws { + public func approve(proposalId: String, namespaces: [String: SessionNamespace]) async throws { try await client.approve(proposalId: proposalId, namespaces: namespaces) } @@ -165,7 +164,7 @@ extension Sign { /// - Parameters: /// - topic: Topic of the session that is intended to be updated. /// - methods: Sets of methods that will replace existing ones. - public func update(topic: String, namespaces: [String : SessionNamespace]) async throws { + public func update(topic: String, namespaces: [String: SessionNamespace]) async throws { try await client.update(topic: topic, namespaces: namespaces) } @@ -202,7 +201,7 @@ extension Sign { /// - Parameters: /// - topic: Topic of the sequence, it can be a pairing or a session topic. /// - completion: Result will be success on response or error on timeout. -- TODO: timeout - public func ping(topic: String, completion: @escaping ((Result) -> ())) { + public func ping(topic: String, completion: @escaping ((Result) -> Void)) { client.ping(topic: topic, completion: completion) } @@ -242,15 +241,15 @@ extension Sign { public func getSessionRequestRecord(id: Int64) -> WalletConnectUtils.JsonRpcRecord? { client.getSessionRequestRecord(id: id) } - + public func connect() throws { try relayClient.connect() } - + public func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws { try relayClient.disconnect(closeCode: closeCode) } - + #if DEBUG /// Delete all stored data sach as: pairings, sessions, keys /// diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index cede3939a..9659ef9d6 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectRelay import WalletConnectUtils @@ -21,9 +20,9 @@ import UIKit /// - delegate: The object that acts as the delegate of WalletConnect Client /// - logger: An object for logging messages public final class SignClient { - + public weak var delegate: SignClientDelegate? - + public let logger: ConsoleLogging private let metadata: AppMetadata private let pairingEngine: PairingEngine @@ -50,9 +49,9 @@ public final class SignClient { /// /// WalletConnect Client is not a singleton but once you create an instance, you should not deinitialize it. Usually only one instance of a client is required in the application. public convenience init(metadata: AppMetadata, projectId: String, relayHost: String, keyValueStorage: KeyValueStorage = UserDefaults.standard) { - self.init(metadata: metadata, projectId: projectId, relayHost: relayHost, logger: ConsoleLogger(loggingLevel: .off), kms: KeyManagementService(serviceIdentifier: "com.walletconnect.sdk"), keyValueStorage: keyValueStorage) + self.init(metadata: metadata, projectId: projectId, relayHost: relayHost, logger: ConsoleLogger(loggingLevel: .off), kms: KeyManagementService(serviceIdentifier: "com.walletconnect.sdk"), keyValueStorage: keyValueStorage) } - + init(metadata: AppMetadata, projectId: String, relayHost: String, logger: ConsoleLogging, kms: KeyManagementService, keyValueStorage: KeyValueStorage) { self.metadata = metadata self.logger = logger @@ -75,7 +74,7 @@ public final class SignClient { setUpConnectionObserving(relayClient: relayClient) setUpEnginesCallbacks() } - + /// Initializes and returns newly created WalletConnect Client Instance. Establishes a network connection with the relay /// /// - Parameters: @@ -84,10 +83,10 @@ public final class SignClient { /// - keyValueStorage: by default WalletConnect SDK will store sequences in UserDefaults but if for some reasons you want to provide your own storage you can inject it here. /// /// WalletConnect Client is not a singleton but once you create an instance, you should not deinitialize it. Usually only one instance of a client is required in the application. - public convenience init(metadata: AppMetadata, relayClient: RelayClient, keyValueStorage: KeyValueStorage = UserDefaults.standard, kms: KeyManagementService = KeyManagementService(serviceIdentifier: "com.walletconnect.sdk")) { + public convenience init(metadata: AppMetadata, relayClient: RelayClient, keyValueStorage: KeyValueStorage = UserDefaults.standard, kms: KeyManagementService = KeyManagementService(serviceIdentifier: "com.walletconnect.sdk")) { self.init(metadata: metadata, relayClient: relayClient, logger: ConsoleLogger(loggingLevel: .off), kms: kms, keyValueStorage: keyValueStorage) } - + init(metadata: AppMetadata, relayClient: RelayClient, logger: ConsoleLogging, kms: KeyManagementService, keyValueStorage: KeyValueStorage) { self.metadata = metadata self.logger = logger @@ -109,7 +108,7 @@ public final class SignClient { setUpConnectionObserving(relayClient: relayClient) setUpEnginesCallbacks() } - + private func setUpConnectionObserving(relayClient: RelayClient) { relayClient.socketConnectionStatusPublisher.sink { [weak self] status in self?.delegate?.didChangeSocketConnectionStatus(status) @@ -134,11 +133,11 @@ public final class SignClient { return nil } else { let pairingURI = try await pairingEngine.create() - try await pairingEngine.propose(pairingTopic: pairingURI.topic, namespaces: requiredNamespaces ,relay: pairingURI.relay) + try await pairingEngine.propose(pairingTopic: pairingURI.topic, namespaces: requiredNamespaces, relay: pairingURI.relay) return pairingURI.absoluteString } } - + /// For responder to receive a session proposal from a proposer /// Responder should call this function in order to accept peer's pairing proposal and be able to subscribe for future session proposals. /// - Parameter uri: Pairing URI that is commonly presented as a QR code by a dapp. @@ -152,7 +151,7 @@ public final class SignClient { } try await pairEngine.pair(pairingURI) } - + /// For the responder to approve a session proposal. /// - Parameters: /// - proposalId: Session Proposal Public key received from peer client in a WalletConnect delegate function: `didReceive(sessionProposal: Session.Proposal)` @@ -160,10 +159,10 @@ public final class SignClient { /// - methods: A Set of methods that the dapp will be allowed to request. /// - events: A Set of events public func approve(proposalId: String, namespaces: [String: SessionNamespace]) async throws { - //TODO - accounts should be validated for matching namespaces BEFORE responding proposal + // TODO - accounts should be validated for matching namespaces BEFORE responding proposal try await approveEngine.approveProposal(proposerPubKey: proposalId, validating: namespaces) } - + /// For the responder to reject a session proposal. /// - Parameters: /// - proposalId: Session Proposal Public key received from peer client in a WalletConnect delegate. @@ -171,7 +170,7 @@ public final class SignClient { public func reject(proposalId: String, reason: RejectionReason) async throws { try await approveEngine.reject(proposerPubKey: proposalId, reason: reason.internalRepresentation()) } - + /// For the responder to update session namespaces /// - Parameters: /// - topic: Topic of the session that is intended to be updated. @@ -179,7 +178,7 @@ public final class SignClient { public func update(topic: String, namespaces: [String: SessionNamespace]) async throws { try await controllerSessionStateMachine.update(topic: topic, namespaces: namespaces) } - + /// For controller to update expiry of a session /// - Parameters: /// - topic: Topic of the Session, it can be a pairing or a session topic. @@ -190,14 +189,14 @@ public final class SignClient { try await controllerSessionStateMachine.extend(topic: topic, by: ttl) } } - + /// For the proposer to send JSON-RPC requests to responding peer. /// - Parameters: /// - params: Parameters defining request and related session public func request(params: Request) async throws { try await sessionEngine.request(params) } - + /// For the responder to respond on pending peer's session JSON-RPC Request /// - Parameters: /// - topic: Topic of the session for which the request was received. @@ -205,7 +204,7 @@ public final class SignClient { public func respond(topic: String, response: JsonRpcResult) async throws { try await sessionEngine.respondSessionRequest(topic: topic, response: response) } - + /// Ping method allows to check if client's peer is online and is subscribing for your sequence topic /// /// Should Error: @@ -216,7 +215,7 @@ public final class SignClient { /// - Parameters: /// - topic: Topic of the sequence, it can be a pairing or a session topic. /// - completion: Result will be success on response or error on timeout. -- TODO: timeout - public func ping(topic: String, completion: @escaping ((Result) -> ())) { + public func ping(topic: String, completion: @escaping ((Result) -> Void)) { if pairingEngine.hasPairing(for: topic) { pairingEngine.ping(topic: topic) { result in completion(result) @@ -227,7 +226,7 @@ public final class SignClient { } } } - + /// For the proposer and responder to emits an event on the peer for an existing session /// /// When: a client wants to emit an event to its peer client (eg. chain changed or tx replaced) @@ -243,7 +242,7 @@ public final class SignClient { public func emit(topic: String, event: Session.Event, chainId: Blockchain) async throws { try await sessionEngine.emit(topic: topic, event: event.internalRepresentation(), chainId: chainId) } - + /// For the proposer and responder to terminate a session /// /// Should Error: @@ -255,33 +254,33 @@ public final class SignClient { public func disconnect(topic: String, reason: Reason) async throws { try await sessionEngine.delete(topic: topic, reason: reason) } - + /// - Returns: All sessions public func getSessions() -> [Session] { sessionEngine.getSessions() } - + /// - Returns: All settled pairings that are active public func getSettledPairings() -> [Pairing] { pairingEngine.getSettledPairings() } - + /// - Returns: Pending requests received with wc_sessionRequest /// - Parameter topic: topic representing session for which you want to get pending requests. If nil, you will receive pending requests for all active sessions. public func getPendingRequests(topic: String? = nil) -> [Request] { let pendingRequests: [Request] = history.getPending() - .filter{$0.request.method == .sessionRequest} + .filter {$0.request.method == .sessionRequest} .compactMap { guard case let .sessionRequest(payloadRequest) = $0.request.params else {return nil} return Request(id: $0.id, topic: $0.topic, method: payloadRequest.request.method, params: payloadRequest.request.params, chainId: payloadRequest.chainId) } if let topic = topic { - return pendingRequests.filter{$0.topic == topic} + return pendingRequests.filter {$0.topic == topic} } else { return pendingRequests } } - + /// - Parameter id: id of a wc_sessionRequest jsonrpc request /// - Returns: json rpc record object for given id or nil if record for give id does not exits public func getSessionRequestRecord(id: Int64) -> WalletConnectUtils.JsonRpcRecord? { @@ -292,7 +291,7 @@ public final class SignClient { } // MARK: - Private - + private func setUpEnginesCallbacks() { approveEngine.onSessionProposal = { [unowned self] proposal in delegate?.didReceive(sessionProposal: proposal) diff --git a/Sources/WalletConnectSign/Sign/SignClientDelegate.swift b/Sources/WalletConnectSign/Sign/SignClientDelegate.swift index dca2f3206..2a3823552 100644 --- a/Sources/WalletConnectSign/Sign/SignClientDelegate.swift +++ b/Sources/WalletConnectSign/Sign/SignClientDelegate.swift @@ -1,40 +1,39 @@ - import Foundation import WalletConnectUtils import WalletConnectRelay /// A protocol that defines methods that SignClient instance call on it's delegate to handle sequences level events public protocol SignClientDelegate: AnyObject { - + /// Tells the delegate that session proposal has been received. /// /// Function is executed on responder client only func didReceive(sessionProposal: Session.Proposal) - + /// Tells the delegate that session payload request has been received /// /// In most cases that function is supposed to be called on wallet client. /// - Parameters: /// - sessionRequest: Object containing request received from peer client. func didReceive(sessionRequest: Request) - + /// Tells the delegate that session payload response has been received /// /// In most cases that function is supposed to be called on dApp client. /// - Parameters: /// - sessionResponse: Object containing response received from peer client. func didReceive(sessionResponse: Response) - + /// Tells the delegate that the peer client has terminated the session. /// /// Function can be executed on any type of the client. func didDelete(sessionTopic: String, reason: Reason) - + /// Tells the delegate that methods has been updated in session /// /// Function is executed on controller and non-controller client when both communicating peers have successfully updated methods requested by the controller client. func didUpdate(sessionTopic: String, namespaces: [String: SessionNamespace]) - + /// Tells the delegate that session expiry has been updated /// /// Function will be executed on controller and non-controller clients. @@ -44,15 +43,15 @@ public protocol SignClientDelegate: AnyObject { /// /// Function is executed on proposer and responder client when both communicating peers have successfully established a session. func didSettle(session: Session) - + /// Tells the delegate that event has been received. func didReceive(event: Session.Event, sessionTopic: String, chainId: Blockchain?) - + /// Tells the delegate that peer client has rejected a session proposal. /// /// Function will be executed on proposer client only. func didReject(proposal: Session.Proposal, reason: Reason) - + /// Tells the delegate that client has connected WebSocket func didChangeSocketConnectionStatus(_ status: SocketConnectionStatus) } diff --git a/Sources/WalletConnectSign/Sign/SignConfig.swift b/Sources/WalletConnectSign/Sign/SignConfig.swift index aaf726aa3..09e84e788 100644 --- a/Sources/WalletConnectSign/Sign/SignConfig.swift +++ b/Sources/WalletConnectSign/Sign/SignConfig.swift @@ -6,7 +6,7 @@ public extension Sign { let metadata: AppMetadata let projectId: String let socketConnectionType: SocketConnectionType - + public init(metadata: AppMetadata, projectId: String, socketConnectionType: SocketConnectionType = .automatic) { self.metadata = metadata self.projectId = projectId diff --git a/Sources/WalletConnectSign/Storage/PairingStorage.swift b/Sources/WalletConnectSign/Storage/PairingStorage.swift index 6fb7c0ec7..211994e03 100644 --- a/Sources/WalletConnectSign/Storage/PairingStorage.swift +++ b/Sources/WalletConnectSign/Storage/PairingStorage.swift @@ -9,38 +9,38 @@ protocol WCPairingStorage: AnyObject { } final class PairingStorage: WCPairingStorage { - + var onPairingExpiration: ((WCPairing) -> Void)? { get { storage.onSequenceExpiration } set { storage.onSequenceExpiration = newValue } } - + private let storage: SequenceStore - + init(storage: SequenceStore) { self.storage = storage } - + func hasPairing(forTopic topic: String) -> Bool { storage.hasSequence(forTopic: topic) } - + func setPairing(_ pairing: WCPairing) { storage.setSequence(pairing) } - + func getPairing(forTopic topic: String) -> WCPairing? { try? storage.getSequence(forTopic: topic) } - + func getAll() -> [WCPairing] { storage.getAll() } - + func delete(topic: String) { storage.delete(topic: topic) } - + func deleteAll() { storage.deleteAll() } diff --git a/Sources/WalletConnectSign/Storage/SequenceStore.swift b/Sources/WalletConnectSign/Storage/SequenceStore.swift index 1be014d6e..8b99b00aa 100644 --- a/Sources/WalletConnectSign/Storage/SequenceStore.swift +++ b/Sources/WalletConnectSign/Storage/SequenceStore.swift @@ -13,7 +13,7 @@ protocol ExpirableSequence: Codable, Expirable { final class SequenceStore where T: ExpirableSequence { var onSequenceExpiration: ((_ sequence: T) -> Void)? - + private let store: CodableStore private let dateInitializer: () -> Date @@ -21,11 +21,11 @@ final class SequenceStore where T: ExpirableSequence { self.store = store self.dateInitializer = dateInitializer } - + func hasSequence(forTopic topic: String) -> Bool { (try? getSequence(forTopic: topic)) != nil } - + func setSequence(_ sequence: T) { store.set(sequence, forKey: sequence.topic) } @@ -43,11 +43,11 @@ final class SequenceStore where T: ExpirableSequence { func delete(topic: String) { store.delete(forKey: topic) } - + func deleteAll() { store.deleteAll() } - + private func verifyExpiry(on sequence: T) -> T? { let now = dateInitializer() if now >= sequence.expiryDate { diff --git a/Sources/WalletConnectSign/Storage/SessionStorage.swift b/Sources/WalletConnectSign/Storage/SessionStorage.swift index a71d455ff..c5ff97bcb 100644 --- a/Sources/WalletConnectSign/Storage/SessionStorage.swift +++ b/Sources/WalletConnectSign/Storage/SessionStorage.swift @@ -9,38 +9,38 @@ protocol WCSessionStorage: AnyObject { } final class SessionStorage: WCSessionStorage { - + var onSessionExpiration: ((WCSession) -> Void)? - + private let storage: SequenceStore - + init(storage: SequenceStore) { self.storage = storage storage.onSequenceExpiration = { [unowned self] session in onSessionExpiration?(session) } } - + func hasSession(forTopic topic: String) -> Bool { storage.hasSequence(forTopic: topic) } - + func setSession(_ session: WCSession) { storage.setSequence(session) } - + func getSession(forTopic topic: String) -> WCSession? { return try? storage.getSequence(forTopic: topic) } - + func getAll() -> [WCSession] { storage.getAll() } - + func delete(topic: String) { storage.delete(topic: topic) } - + func deleteAll() { storage.deleteAll() } diff --git a/Sources/WalletConnectSign/StorageDomainIdentifiers.swift b/Sources/WalletConnectSign/StorageDomainIdentifiers.swift index a74de51f5..1e0c2a799 100644 --- a/Sources/WalletConnectSign/StorageDomainIdentifiers.swift +++ b/Sources/WalletConnectSign/StorageDomainIdentifiers.swift @@ -1,4 +1,3 @@ - import Foundation enum StorageDomainIdentifiers: String { diff --git a/Sources/WalletConnectSign/Subscription/WCRequestSubscriptionPayload.swift b/Sources/WalletConnectSign/Subscription/WCRequestSubscriptionPayload.swift index a0128bec1..591d10d53 100644 --- a/Sources/WalletConnectSign/Subscription/WCRequestSubscriptionPayload.swift +++ b/Sources/WalletConnectSign/Subscription/WCRequestSubscriptionPayload.swift @@ -1,4 +1,3 @@ - import Foundation struct WCRequestSubscriptionPayload: Codable { diff --git a/Sources/WalletConnectSign/Types/Common/AppMetadata.swift b/Sources/WalletConnectSign/Types/Common/AppMetadata.swift index a5a71b5a7..531bd5fe3 100644 --- a/Sources/WalletConnectSign/Types/Common/AppMetadata.swift +++ b/Sources/WalletConnectSign/Types/Common/AppMetadata.swift @@ -1,4 +1,3 @@ - import Foundation /** @@ -11,19 +10,19 @@ import Foundation suitable place to briefly communicate your brand. */ public struct AppMetadata: Codable, Equatable { - + /// The name of the app. public let name: String - + /// A brief textual description of the app that can be displayed to peers. public let description: String - + /// The URL string that identifies the official domain of the app. public let url: String - + /// An array of URL strings pointing to the icon assets on the web. public let icons: [String] - + /** Creates a new metadata object with the specified information. diff --git a/Sources/WalletConnectSign/Types/Common/Participant.swift b/Sources/WalletConnectSign/Types/Common/Participant.swift index 604427926..0f0f4502a 100644 --- a/Sources/WalletConnectSign/Types/Common/Participant.swift +++ b/Sources/WalletConnectSign/Types/Common/Participant.swift @@ -1,8 +1,7 @@ - struct Participant: Codable, Equatable { let publicKey: String let metadata: AppMetadata - + init(publicKey: String, metadata: AppMetadata) { self.publicKey = publicKey self.metadata = metadata diff --git a/Sources/WalletConnectSign/Types/Common/RelayProtocolOptions.swift b/Sources/WalletConnectSign/Types/Common/RelayProtocolOptions.swift index e6d2d99ad..2d0009aa9 100644 --- a/Sources/WalletConnectSign/Types/Common/RelayProtocolOptions.swift +++ b/Sources/WalletConnectSign/Types/Common/RelayProtocolOptions.swift @@ -1,4 +1,3 @@ - import Foundation struct RelayProtocolOptions: Codable, Equatable { diff --git a/Sources/WalletConnectSign/Types/Pairing/PairingProposal.swift b/Sources/WalletConnectSign/Types/Pairing/PairingProposal.swift index ef404d637..ac6dae8a7 100644 --- a/Sources/WalletConnectSign/Types/Pairing/PairingProposal.swift +++ b/Sources/WalletConnectSign/Types/Pairing/PairingProposal.swift @@ -1,8 +1,5 @@ - import Foundation - struct PairingState: Codable, Equatable { var metadata: AppMetadata? } - diff --git a/Sources/WalletConnectSign/Types/Pairing/PairingType.swift b/Sources/WalletConnectSign/Types/Pairing/PairingType.swift index c26e005e2..d814e4449 100644 --- a/Sources/WalletConnectSign/Types/Pairing/PairingType.swift +++ b/Sources/WalletConnectSign/Types/Pairing/PairingType.swift @@ -1,4 +1,3 @@ - import Foundation // Internal namespace for pairing payloads. @@ -7,11 +6,11 @@ internal enum PairingType { struct DeleteParams: Codable, Equatable { let reason: Reason } - + struct Reason: Codable, Equatable { let code: Int let message: String } - + struct PingParams: Codable, Equatable {} } diff --git a/Sources/WalletConnectSign/Types/Pairing/WCPairing.swift b/Sources/WalletConnectSign/Types/Pairing/WCPairing.swift index e5f93d314..df9cb4d00 100644 --- a/Sources/WalletConnectSign/Types/Pairing/WCPairing.swift +++ b/Sources/WalletConnectSign/Types/Pairing/WCPairing.swift @@ -7,21 +7,21 @@ struct WCPairing: ExpirableSequence { var peerMetadata: AppMetadata? private (set) var expiryDate: Date private (set) var active: Bool - + #if DEBUG static var dateInitializer: () -> Date = Date.init #else private static var dateInitializer: () -> Date = Date.init #endif - + static var timeToLiveInactive: TimeInterval { 5 * .minute } - + static var timeToLiveActive: TimeInterval { 30 * .day } - + init(topic: String, relay: RelayProtocolOptions, peerMetadata: AppMetadata, isActive: Bool = false, expiryDate: Date) { self.topic = topic self.relay = relay @@ -29,26 +29,26 @@ struct WCPairing: ExpirableSequence { self.active = isActive self.expiryDate = expiryDate } - + init(topic: String) { self.topic = topic self.relay = RelayProtocolOptions(protocol: "waku", data: nil) self.active = false self.expiryDate = Self.dateInitializer().advanced(by: Self.timeToLiveInactive) } - + init(uri: WalletConnectURI) { self.topic = uri.topic self.relay = uri.relay self.active = false self.expiryDate = Self.dateInitializer().advanced(by: Self.timeToLiveInactive) } - + mutating func activate() { active = true try? updateExpiry() } - + mutating func updateExpiry(_ ttl: TimeInterval = WCPairing.timeToLiveActive) throws { let now = Self.dateInitializer() let newExpiryDate = now.advanced(by: ttl) diff --git a/Sources/WalletConnectSign/Types/ReasonCode.swift b/Sources/WalletConnectSign/Types/ReasonCode.swift index c6a05c492..61061e9b6 100644 --- a/Sources/WalletConnectSign/Types/ReasonCode.swift +++ b/Sources/WalletConnectSign/Types/ReasonCode.swift @@ -1,20 +1,20 @@ enum ReasonCode { - + enum Context: String { case pairing = "pairing" case session = "session" } - + // 0 (Generic) case generic(message: String) - + // 1000 (Internal) case missingOrInvalid(String) case invalidUpdateAccountsRequest case invalidUpdateNamespaceRequest case invalidUpdateExpiryRequest case noContextWithTopic(context: Context, topic: String) - + // 3000 (Unauthorized) case unauthorizedTargetChain(String) case unauthorizedMethod(String) @@ -23,7 +23,7 @@ enum ReasonCode { case unauthorizedUpdateNamespacesRequest case unauthorizedUpdateExpiryRequest case unauthorizedMatchingController(isController: Bool) - + // 5000 case disapprovedChains case disapprovedMethods @@ -33,21 +33,21 @@ enum ReasonCode { case unsupportedEvents case unsupportedAccounts case unsupportedNamespaceKey - + var code: Int { switch self { case .generic: return 0 case .missingOrInvalid: return 1000 - + case .invalidUpdateAccountsRequest: return 1003 case .invalidUpdateNamespaceRequest: return 1004 case .invalidUpdateExpiryRequest: return 1005 case .noContextWithTopic: return 1301 - + case .unauthorizedTargetChain: return 3000 case .unauthorizedMethod: return 3001 case .unauthorizedEvent: return 3002 - + case .unauthorizedUpdateAccountRequest: return 3003 case .unauthorizedUpdateNamespacesRequest: return 3004 case .unauthorizedUpdateExpiryRequest: return 3005 @@ -55,7 +55,7 @@ enum ReasonCode { case .disapprovedChains: return 5000 case .disapprovedMethods: return 5001 case .disapprovedEventTypes: return 5002 - + case .unsupportedChains: return 5100 case .unsupportedMethods: return 5101 case .unsupportedEvents: return 5102 @@ -63,7 +63,7 @@ enum ReasonCode { case .unsupportedNamespaceKey: return 5104 } } - + var message: String { switch self { case .generic(let message): diff --git a/Sources/WalletConnectSign/Types/Session/SessionProposal.swift b/Sources/WalletConnectSign/Types/Session/SessionProposal.swift index 017d54f56..ae26cc810 100644 --- a/Sources/WalletConnectSign/Types/Session/SessionProposal.swift +++ b/Sources/WalletConnectSign/Types/Session/SessionProposal.swift @@ -1,11 +1,10 @@ - import Foundation struct SessionProposal: Codable, Equatable { let relays: [RelayProtocolOptions] let proposer: Participant let requiredNamespaces: [String: ProposalNamespace] - + func publicRepresentation() -> Session.Proposal { return Session.Proposal(id: proposer.publicKey, proposer: proposer.metadata, requiredNamespaces: requiredNamespaces, proposal: self) } diff --git a/Sources/WalletConnectSign/Types/Session/SessionType.swift b/Sources/WalletConnectSign/Types/Session/SessionType.swift index ec4baf6c9..054704eae 100644 --- a/Sources/WalletConnectSign/Types/Session/SessionType.swift +++ b/Sources/WalletConnectSign/Types/Session/SessionType.swift @@ -3,47 +3,47 @@ import WalletConnectUtils // Internal namespace for session payloads. internal enum SessionType { - + typealias ProposeParams = SessionProposal - + struct ProposeResponse: Codable, Equatable { let relay: RelayProtocolOptions let responderPublicKey: String } - + struct SettleParams: Codable, Equatable { let relay: RelayProtocolOptions let controller: Participant let namespaces: [String: SessionNamespace] let expiry: Int64 } - + struct UpdateParams: Codable, Equatable { let namespaces: [String: SessionNamespace] } typealias DeleteParams = SessionType.Reason - + struct Reason: Codable, Equatable { let code: Int let message: String - + init(code: Int, message: String) { self.code = code self.message = message } } - + struct RequestParams: Codable, Equatable { let request: Request let chainId: Blockchain - + struct Request: Codable, Equatable { let method: String let params: AnyCodable } } - + struct EventParams: Codable, Equatable { let event: Event let chainId: Blockchain @@ -51,15 +51,15 @@ internal enum SessionType { struct Event: Codable, Equatable { let name: String let data: AnyCodable - + func publicRepresentation() -> Session.Event { Session.Event(name: name, data: data) } } } - - struct PingParams: Codable, Equatable {} - + + struct PingParams: Codable, Equatable {} + struct UpdateExpiryParams: Codable, Equatable { let expiry: Int64 } diff --git a/Sources/WalletConnectSign/Types/Session/WCSession.swift b/Sources/WalletConnectSign/Types/Session/WCSession.swift index ae1d439ad..52cc5aede 100644 --- a/Sources/WalletConnectSign/Types/Session/WCSession.swift +++ b/Sources/WalletConnectSign/Types/Session/WCSession.swift @@ -14,7 +14,7 @@ struct WCSession: ExpirableSequence { var acknowledged: Bool let controller: AgreementPeer private(set) var namespaces: [String: SessionNamespace] - + static var defaultTimeToLive: Int64 { Int64(7*Time.day) } @@ -22,7 +22,7 @@ struct WCSession: ExpirableSequence { var publicKey: String? { selfParticipant.publicKey } - + init(topic: String, selfParticipant: Participant, peerParticipant: Participant, @@ -37,7 +37,7 @@ struct WCSession: ExpirableSequence { self.acknowledged = acknowledged self.expiryDate = Date(timeIntervalSince1970: TimeInterval(settleParams.expiry)) } - + #if DEBUG internal init(topic: String, relay: RelayProtocolOptions, controller: AgreementPeer, selfParticipant: Participant, peerParticipant: Participant, namespaces: [String: SessionNamespace], events: Set, accounts: Set, acknowledged: Bool, expiry: Int64) { self.topic = topic @@ -50,23 +50,23 @@ struct WCSession: ExpirableSequence { self.expiryDate = Date(timeIntervalSince1970: TimeInterval(expiry)) } #endif - + mutating func acknowledge() { self.acknowledged = true } - + var selfIsController: Bool { return controller.publicKey == selfParticipant.publicKey } - + var peerIsController: Bool { return controller.publicKey == peerParticipant.publicKey } - + func hasNamespace(for chain: Blockchain) -> Bool { return namespaces[chain.namespace] != nil } - + func hasPermission(forMethod method: String, onChain chain: Blockchain) -> Bool { if let namespace = namespaces[chain.namespace] { if namespace.accounts.contains(where: { $0.blockchain == chain }) { @@ -86,7 +86,7 @@ struct WCSession: ExpirableSequence { } return false } - + func hasPermission(forEvent event: String, onChain chain: Blockchain) -> Bool { if let namespace = namespaces[chain.namespace] { if namespace.accounts.contains(where: { $0.blockchain == chain }) { @@ -110,7 +110,7 @@ struct WCSession: ExpirableSequence { mutating func updateNamespaces(_ namespaces: [String: SessionNamespace]) { self.namespaces = namespaces } - + /// updates session expiry by given ttl /// - Parameter ttl: time the session expiry should be updated by - in seconds mutating func updateExpiry(by ttl: Int64) throws { @@ -121,7 +121,7 @@ struct WCSession: ExpirableSequence { } expiryDate = newExpiryDate } - + /// updates session expiry to given timestamp /// - Parameter expiry: timestamp in the future in seconds mutating func updateExpiry(to expiry: Int64) throws { diff --git a/Sources/WalletConnectSign/Types/WCMethod.swift b/Sources/WalletConnectSign/Types/WCMethod.swift index 7864e7b20..cbe97b754 100644 --- a/Sources/WalletConnectSign/Types/WCMethod.swift +++ b/Sources/WalletConnectSign/Types/WCMethod.swift @@ -8,7 +8,7 @@ enum WCMethod { case wcSessionRequest(SessionType.RequestParams) case wcSessionPing case wcSessionEvent(SessionType.EventParams) - + func asRequest() -> WCRequest { switch self { case .wcPairingPing: diff --git a/Sources/WalletConnectSign/Types/WCRequest.swift b/Sources/WalletConnectSign/Types/WCRequest.swift index a6fa8b861..57e481de4 100644 --- a/Sources/WalletConnectSign/Types/WCRequest.swift +++ b/Sources/WalletConnectSign/Types/WCRequest.swift @@ -5,21 +5,21 @@ struct WCRequest: Codable { let jsonrpc: String let method: Method let params: Params - + enum CodingKeys: CodingKey { case id case jsonrpc case method case params } - + internal init(id: Int64 = generateId(), jsonrpc: String = "2.0", method: Method, params: Params) { self.id = id self.jsonrpc = jsonrpc self.method = method self.params = params } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int64.self, forKey: .id) @@ -58,7 +58,7 @@ struct WCRequest: Codable { params = .sessionEvent(paramsValue) } } - + func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) diff --git a/Sources/WalletConnectSign/Types/WalletConnectURI.swift b/Sources/WalletConnectSign/Types/WalletConnectURI.swift index b47bc658c..0d43287a6 100644 --- a/Sources/WalletConnectSign/Types/WalletConnectURI.swift +++ b/Sources/WalletConnectSign/Types/WalletConnectURI.swift @@ -1,19 +1,19 @@ import Foundation public struct WalletConnectURI: Equatable { - + let topic: String let version: String let symKey: String let relay: RelayProtocolOptions - + init(topic: String, symKey: String, relay: RelayProtocolOptions) { self.version = "2" self.topic = topic self.symKey = symKey self.relay = relay } - + public init?(string: String) { guard string.hasPrefix("wc:") else { return nil @@ -23,7 +23,7 @@ public struct WalletConnectURI: Equatable { return nil } let query: [String: String]? = components.queryItems?.reduce(into: [:]) { $0[$1.name] = $1.value } - + guard let topic = components.user, let version = components.host, let symKey = query?["symKey"], @@ -35,11 +35,11 @@ public struct WalletConnectURI: Equatable { self.symKey = symKey self.relay = RelayProtocolOptions(protocol: relayProtocol, data: relayData) } - + public var absoluteString: String { return "wc:\(topic)@\(version)?symKey=\(symKey)&\(relayQuery)" } - + private var relayQuery: String { var query = "relay-protocol=\(relay.protocol)" if let relayData = relay.data { diff --git a/Sources/WalletConnectSign/WalletConnectError.swift b/Sources/WalletConnectSign/WalletConnectError.swift index f46157a78..dd6d21361 100644 --- a/Sources/WalletConnectSign/WalletConnectError.swift +++ b/Sources/WalletConnectSign/WalletConnectError.swift @@ -1,5 +1,5 @@ enum WalletConnectError: Error { - + case pairingProposalFailed case malformedPairingURI case noPairingMatchingTopic(String) @@ -14,9 +14,9 @@ enum WalletConnectError: Error { case topicGenerationFailed case invalidPermissions // TODO: Refactor into actual cases case unsupportedNamespace(ReasonCode) - + case `internal`(_ reason: InternalReason) - + enum InternalReason: Error { case jsonRpcDuplicateDetected case noJsonRpcRequestMatchingResponse @@ -24,7 +24,7 @@ enum WalletConnectError: Error { } extension WalletConnectError { - + var localizedDescription: String { switch self { case .pairingProposalFailed: @@ -55,7 +55,7 @@ extension WalletConnectError { return "Invalid permissions for call." case .unsupportedNamespace(let reason): return reason.message - case .internal(_): // TODO: Remove internal case + case .internal: // TODO: Remove internal case return "" } } diff --git a/Sources/WalletConnectUtils/Account.swift b/Sources/WalletConnectUtils/Account.swift index d754f66ba..7d5c2cbee 100644 --- a/Sources/WalletConnectUtils/Account.swift +++ b/Sources/WalletConnectUtils/Account.swift @@ -11,26 +11,26 @@ [CAIP-10]:https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md */ public struct Account: Equatable, Hashable { - + /// A blockchain namespace. Usually describes an ecosystem or standard. public let namespace: String - + /// A reference string that identifies a blockchain within a given namespace. public let reference: String - + /// The account's address specific to the blockchain. public let address: String - + /// The CAIP-2 blockchain identifier of the account. public var blockchainIdentifier: String { "\(namespace):\(reference)" } - + /// The CAIP-10 account identifier absolute string. public var absoluteString: String { "\(namespace):\(reference):\(address)" } - + /// Returns a CAIP-2 reference to the blockchain where the account is located. public var blockchain: Blockchain { guard let blockchain = Blockchain(namespace: namespace, reference: reference) else { @@ -38,7 +38,7 @@ public struct Account: Equatable, Hashable { } return blockchain } - + /** Creates an account instance from the provided string. @@ -52,7 +52,7 @@ public struct Account: Equatable, Hashable { self.reference = String(splits[1]) self.address = String(splits[2]) } - + /** Creates an account instance from a chain ID and an address. @@ -62,7 +62,7 @@ public struct Account: Equatable, Hashable { public init?(chainIdentifier: String, address: String) { self.init("\(chainIdentifier):\(address)") } - + /** Creates an account instance from a blockchain reference and an address. @@ -80,7 +80,7 @@ extension Account: LosslessStringConvertible { } extension Account: Codable { - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let absoluteString = try container.decode(String.self) @@ -89,7 +89,7 @@ extension Account: Codable { } self = account } - + public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(absoluteString) diff --git a/Sources/WalletConnectUtils/Blockchain.swift b/Sources/WalletConnectUtils/Blockchain.swift index 97eb7f5cd..8d920f01d 100644 --- a/Sources/WalletConnectUtils/Blockchain.swift +++ b/Sources/WalletConnectUtils/Blockchain.swift @@ -9,18 +9,18 @@ [CAIP-2]:https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md */ public struct Blockchain: Equatable, Hashable { - + /// A blockchain namespace. Usually describes an ecosystem or standard. public let namespace: String - + /// A reference string that identifies a blockchain within a given namespace. public let reference: String - + /// The CAIP-2 blockchain identifier string. public var absoluteString: String { "\(namespace):\(reference)" } - + /** Creates an instance of a blockchain reference from a string. @@ -33,7 +33,7 @@ public struct Blockchain: Equatable, Hashable { self.namespace = String(splits[0]) self.reference = String(splits[1]) } - + /** Creates an instance of a blockchain reference from a namespace and a reference string. @@ -52,7 +52,7 @@ extension Blockchain: LosslessStringConvertible { } extension Blockchain: Codable { - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let absoluteString = try container.decode(String.self) @@ -61,7 +61,7 @@ extension Blockchain: Codable { } self = blockchain } - + public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(absoluteString) diff --git a/Sources/WalletConnectUtils/CodableStore.swift b/Sources/WalletConnectUtils/CodableStore.swift index c1356a31f..184988696 100644 --- a/Sources/WalletConnectUtils/CodableStore.swift +++ b/Sources/WalletConnectUtils/CodableStore.swift @@ -1,4 +1,3 @@ - import Foundation public final class CodableStore where T: Codable { @@ -35,17 +34,17 @@ public final class CodableStore where T: Codable { public func delete(forKey key: String) { defaults.removeObject(forKey: getContextPrefixedKey(for: key)) } - + public func deleteAll() { dictionaryForIdentifier() .forEach { defaults.removeObject(forKey: $0.key) } } - + private func getContextPrefixedKey(for key: String) -> String { return "\(prefix).\(key)" } - - private func dictionaryForIdentifier() -> [String : Any] { + + private func dictionaryForIdentifier() -> [String: Any] { return defaults.dictionaryRepresentation() .filter { $0.key.hasPrefix("\(prefix).") } } diff --git a/Sources/WalletConnectUtils/Data+Extension.swift b/Sources/WalletConnectUtils/Data+Extension.swift index 2f9e0284c..88624109f 100644 --- a/Sources/WalletConnectUtils/Data+Extension.swift +++ b/Sources/WalletConnectUtils/Data+Extension.swift @@ -3,7 +3,7 @@ import Foundation // MARK: - Random data generation extension Data { - + public static func randomBytes(count: Int) -> Data { var buffer = [UInt8](repeating: 0, count: count) let status = SecRandomCopyBytes(kSecRandomDefault, count, &buffer) diff --git a/Sources/WalletConnectUtils/Encodable.swift b/Sources/WalletConnectUtils/Encodable.swift index 604d58eda..74d14671c 100644 --- a/Sources/WalletConnectUtils/Encodable.swift +++ b/Sources/WalletConnectUtils/Encodable.swift @@ -7,7 +7,7 @@ public enum DataConversionError: Error { case dataToStringFailed } -public extension Encodable { +public extension Encodable { func json() throws -> String { let data = try JSONEncoder().encode(self) guard let string = String(data: data, encoding: .utf8) else { diff --git a/Sources/WalletConnectUtils/Extensions/String+Extension.swift b/Sources/WalletConnectUtils/Extensions/String+Extension.swift index b121e56ff..433a7e537 100644 --- a/Sources/WalletConnectUtils/Extensions/String+Extension.swift +++ b/Sources/WalletConnectUtils/Extensions/String+Extension.swift @@ -1,11 +1,11 @@ import Foundation extension String { - + static let chainNamespaceRegex = "^[-a-z0-9]{3,8}$" static let chainReferenceRegex = "^[-a-zA-Z0-9]{1,32}$" static let accountAddressRegex = "^[a-zA-Z0-9]{1,64}$" - + static func conformsToCAIP2(_ string: String) -> Bool { let splits = string.split(separator: ":", omittingEmptySubsequences: false) guard splits.count == 2 else { return false } @@ -15,7 +15,7 @@ extension String { let isReferenceValid = (reference.range(of: chainReferenceRegex, options: .regularExpression) != nil) return isNamespaceValid && isReferenceValid } - + static func conformsToCAIP10(_ string: String) -> Bool { let splits = string.split(separator: ":", omittingEmptySubsequences: false) guard splits.count == 3 else { return false } diff --git a/Sources/WalletConnectUtils/Extensions/String.swift b/Sources/WalletConnectUtils/Extensions/String.swift index 360c2eff7..9da7ff9ab 100644 --- a/Sources/WalletConnectUtils/Extensions/String.swift +++ b/Sources/WalletConnectUtils/Extensions/String.swift @@ -4,20 +4,20 @@ public extension String { func toHexEncodedString(uppercase: Bool = true, prefix: String = "", separator: String = "") -> String { return unicodeScalars.map { prefix + .init($0.value, radix: 16, uppercase: uppercase) } .joined(separator: separator) } - + static func generateTopic() -> String { let keyData = Data.randomBytes(count: 32) return keyData.toHexString() } - - init(rawRepresentation data: D) throws where D : ContiguousBytes { + + init(rawRepresentation data: D) throws where D: ContiguousBytes { let bytes = data.withUnsafeBytes { Data(Array($0)) } guard let string = String(data: bytes, encoding: .utf8) else { fatalError() // FIXME: Throw error } self = string } - + var rawRepresentation: Data { self.data(using: .utf8) ?? Data() } diff --git a/Sources/WalletConnectUtils/JSONRPC/JSONRPCErrorResponse.swift b/Sources/WalletConnectUtils/JSONRPC/JSONRPCErrorResponse.swift index bad700e14..15f2c3de1 100644 --- a/Sources/WalletConnectUtils/JSONRPC/JSONRPCErrorResponse.swift +++ b/Sources/WalletConnectUtils/JSONRPC/JSONRPCErrorResponse.swift @@ -1,4 +1,3 @@ - import Foundation public struct JSONRPCErrorResponse: Error, Equatable, Codable { @@ -16,7 +15,7 @@ public struct JSONRPCErrorResponse: Error, Equatable, Codable { self.id = id self.error = error } - + public struct Error: Codable, Equatable { public let code: Int public let message: String diff --git a/Sources/WalletConnectUtils/JSONRPC/JSONRPCRequest.swift b/Sources/WalletConnectUtils/JSONRPC/JSONRPCRequest.swift index 7b755421f..49520a703 100644 --- a/Sources/WalletConnectUtils/JSONRPC/JSONRPCRequest.swift +++ b/Sources/WalletConnectUtils/JSONRPC/JSONRPCRequest.swift @@ -3,19 +3,19 @@ import Foundation public struct JSONRPCRequest: Codable, Equatable { - + public let id: Int64 public let jsonrpc: String public let method: String public let params: T - + enum CodingKeys: CodingKey { case id case jsonrpc case method case params } - + public init(id: Int64 = JSONRPCRequest.generateId(), method: String, params: T) { self.id = id self.jsonrpc = "2.0" diff --git a/Sources/WalletConnectUtils/JSONRPC/JSONRPCResponse.swift b/Sources/WalletConnectUtils/JSONRPC/JSONRPCResponse.swift index 7ef3d4adb..e7dd48923 100644 --- a/Sources/WalletConnectUtils/JSONRPC/JSONRPCResponse.swift +++ b/Sources/WalletConnectUtils/JSONRPC/JSONRPCResponse.swift @@ -1,4 +1,3 @@ - import Foundation public struct JSONRPCResponse: Codable, Equatable { diff --git a/Sources/WalletConnectUtils/JSONRPC/JsonRpcResult.swift b/Sources/WalletConnectUtils/JSONRPC/JsonRpcResult.swift index f7fee74f8..e48c4735d 100644 --- a/Sources/WalletConnectUtils/JSONRPC/JsonRpcResult.swift +++ b/Sources/WalletConnectUtils/JSONRPC/JsonRpcResult.swift @@ -1,7 +1,5 @@ - import Foundation - public enum JsonRpcResult: Codable { case error(JSONRPCErrorResponse) case response(JSONRPCResponse) diff --git a/Sources/WalletConnectUtils/JsonRpcHistory.swift b/Sources/WalletConnectUtils/JsonRpcHistory.swift index 19fa7d17c..9616b794b 100644 --- a/Sources/WalletConnectUtils/JsonRpcHistory.swift +++ b/Sources/WalletConnectUtils/JsonRpcHistory.swift @@ -1,4 +1,3 @@ - import Foundation public class JsonRpcHistory where T: Codable&Equatable { @@ -13,11 +12,11 @@ public class JsonRpcHistory where T: Codable&Equatable { self.logger = logger self.storage = keyValueStore } - + public func get(id: Int64) -> JsonRpcRecord? { try? storage.get(key: "\(id)") } - + public func set(topic: String, request: JSONRPCRequest, chainId: String? = nil) throws { guard !exist(id: request.id) else { throw RecordingError.jsonRpcDuplicateDetected @@ -26,7 +25,7 @@ public class JsonRpcHistory where T: Codable&Equatable { let record = JsonRpcRecord(id: request.id, topic: topic, request: JsonRpcRecord.Request(method: request.method, params: AnyCodable(request.params)), response: nil, chainId: chainId) storage.set(record, forKey: "\(request.id)") } - + public func delete(topic: String) { storage.getAll().forEach { record in if record.topic == topic { @@ -34,7 +33,7 @@ public class JsonRpcHistory where T: Codable&Equatable { } } } - + public func resolve(response: JsonRpcResult) throws -> JsonRpcRecord { logger.debug("Resolving JSON-RPC response - ID: \(response.id)") guard var record = try? storage.get(key: "\(response.id)") else { @@ -48,12 +47,12 @@ public class JsonRpcHistory where T: Codable&Equatable { return record } } - + public func exist(id: Int64) -> Bool { return (try? storage.get(key: "\(id)")) != nil } - + public func getPending() -> [JsonRpcRecord] { - storage.getAll().filter{$0.response == nil} + storage.getAll().filter {$0.response == nil} } } diff --git a/Sources/WalletConnectUtils/JsonRpcRecord.swift b/Sources/WalletConnectUtils/JsonRpcRecord.swift index 151f51651..48013221f 100644 --- a/Sources/WalletConnectUtils/JsonRpcRecord.swift +++ b/Sources/WalletConnectUtils/JsonRpcRecord.swift @@ -1,4 +1,3 @@ - import Foundation public struct JsonRpcRecord: Codable { @@ -7,7 +6,7 @@ public struct JsonRpcRecord: Codable { public let request: Request public var response: JsonRpcResult? public let chainId: String? - + public init(id: Int64, topic: String, request: JsonRpcRecord.Request, response: JsonRpcResult? = nil, chainId: String?) { self.id = id self.topic = topic @@ -15,15 +14,14 @@ public struct JsonRpcRecord: Codable { self.response = response self.chainId = chainId } - + public struct Request: Codable { public let method: String public let params: AnyCodable - + public init(method: String, params: AnyCodable) { self.method = method self.params = params } } } - diff --git a/Sources/WalletConnectUtils/KeyValueStorage.swift b/Sources/WalletConnectUtils/KeyValueStorage.swift index 9c16e19ab..0dd770fe2 100644 --- a/Sources/WalletConnectUtils/KeyValueStorage.swift +++ b/Sources/WalletConnectUtils/KeyValueStorage.swift @@ -11,16 +11,16 @@ public protocol KeyValueStorage { /// Removes the value of the specified default key. func removeObject(forKey defaultName: String) /// Returns a dictionary that contains a union of all key-value pairs in the domains in the search list. - func dictionaryRepresentation() -> [String : Any] + func dictionaryRepresentation() -> [String: Any] } extension UserDefaults: KeyValueStorage {} public final class RuntimeKeyValueStorage: KeyValueStorage { - private var storage: [String : Any] = [:] + private var storage: [String: Any] = [:] private let queue = DispatchQueue(label: "com.walletconnect.sdk.runtimestorage") - - public init(storage: [String : Any] = [:]) { + + public init(storage: [String: Any] = [:]) { self.storage = storage } @@ -48,7 +48,7 @@ public final class RuntimeKeyValueStorage: KeyValueStorage { } } - public func dictionaryRepresentation() -> [String : Any] { + public func dictionaryRepresentation() -> [String: Any] { queue.sync { return storage } diff --git a/Sources/WalletConnectUtils/Logger.swift b/Sources/WalletConnectUtils/Logger.swift index d98c178de..f88360312 100644 --- a/Sources/WalletConnectUtils/Logger.swift +++ b/Sources/WalletConnectUtils/Logger.swift @@ -1,27 +1,26 @@ - import Foundation /// Logging Protocol public protocol ConsoleLogging { /// Writes a debug message to the log. func debug(_ items: Any...) - + /// Writes an informative message to the log. func info(_ items: Any...) - + /// Writes information about a warning to the log. func warn(_ items: Any...) - + /// Writes information about an error to the log. func error(_ items: Any...) - + func setLogging(level: LoggingLevel) } public class ConsoleLogger: ConsoleLogging { private var loggingLevel: LoggingLevel private var suffix: String - + public func setLogging(level: LoggingLevel) { self.loggingLevel = level } @@ -30,7 +29,7 @@ public class ConsoleLogger: ConsoleLogging { self.suffix = suffix ?? "" self.loggingLevel = loggingLevel } - + public func debug(_ items: Any...) { if loggingLevel >= .debug { items.forEach { @@ -38,7 +37,7 @@ public class ConsoleLogger: ConsoleLogging { } } } - + public func info(_ items: Any...) { if loggingLevel >= .info { items.forEach { @@ -46,7 +45,7 @@ public class ConsoleLogger: ConsoleLogging { } } } - + public func warn(_ items: Any...) { if loggingLevel >= .warn { items.forEach { @@ -54,7 +53,7 @@ public class ConsoleLogger: ConsoleLogging { } } } - + public func error(_ items: Any...) { if loggingLevel >= .error { items.forEach { diff --git a/Sources/WalletConnectUtils/Queue.swift b/Sources/WalletConnectUtils/Queue.swift index 1bdedd1a5..29af4ef69 100644 --- a/Sources/WalletConnectUtils/Queue.swift +++ b/Sources/WalletConnectUtils/Queue.swift @@ -1,4 +1,3 @@ - import Foundation public class Queue { @@ -10,23 +9,23 @@ public class Queue { return elements.first } } - + public var tail: T? { serialQueue.sync { return elements.last } } - + public init(elements: [T] = []) { self.elements = elements } - + public func enqueue(_ value: T) { serialQueue.sync { elements.append(value) } } - + public func dequeue() -> T? { serialQueue.sync { if elements.isEmpty { diff --git a/Sources/WalletConnectUtils/TimeInterval+Extension.swift b/Sources/WalletConnectUtils/TimeInterval+Extension.swift index 9409a3496..5b5119cf7 100644 --- a/Sources/WalletConnectUtils/TimeInterval+Extension.swift +++ b/Sources/WalletConnectUtils/TimeInterval+Extension.swift @@ -1,15 +1,15 @@ import Foundation public extension TimeInterval { - + static var day: TimeInterval { 24 * .hour } - + static var hour: TimeInterval { 60 * .minute } - + static var minute: TimeInterval { 60 } diff --git a/Tests/ChatTests/EndToEndTests.swift b/Tests/ChatTests/EndToEndTests.swift index e95c447c2..10b13c541 100644 --- a/Tests/ChatTests/EndToEndTests.swift +++ b/Tests/ChatTests/EndToEndTests.swift @@ -1,4 +1,3 @@ - import Foundation import XCTest @testable import Chat @@ -13,13 +12,13 @@ final class ChatTests: XCTestCase { var client2: Chat! var registry: KeyValueRegistry! private var publishers = [AnyCancellable]() - + override func setUp() { registry = KeyValueRegistry() client1 = makeClient(prefix: "🦖") client2 = makeClient(prefix: "🍄") } - + private func waitClientsConnected() async { let group = DispatchGroup() group.enter() @@ -38,7 +37,7 @@ final class ChatTests: XCTestCase { group.wait() return } - + func makeClient(prefix: String) -> Chat { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) let relayHost = "relay.walletconnect.com" @@ -48,7 +47,7 @@ final class ChatTests: XCTestCase { return Chat(registry: registry, relayClient: relayClient, kms: KeyManagementService(keychain: keychain), logger: logger, keyValueStorage: RuntimeKeyValueStorage()) } - + func testInvite() async { await waitClientsConnected() let inviteExpectation = expectation(description: "invitation expectation") @@ -60,8 +59,7 @@ final class ChatTests: XCTestCase { }.store(in: &publishers) wait(for: [inviteExpectation], timeout: 4) } - - + // func testNewThread() async { // await waitClientsConnected() // let newThreadExpectation = expectation(description: "new thread expectation") diff --git a/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift b/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift index 30f6e4a50..890d00ecd 100644 --- a/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift +++ b/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift @@ -1,4 +1,3 @@ - import Foundation @testable import Chat @@ -8,7 +7,7 @@ class NetworkingInteractorMock: NetworkInteracting { func subscribe(topic: String) async throws { subscriptions.append(topic) } - + func didSubscribe(to topic: String) -> Bool { subscriptions.contains { $0 == topic } } diff --git a/Tests/ChatTests/RegistryManagerTests.swift b/Tests/ChatTests/RegistryManagerTests.swift index f68398003..fc3ee495a 100644 --- a/Tests/ChatTests/RegistryManagerTests.swift +++ b/Tests/ChatTests/RegistryManagerTests.swift @@ -11,7 +11,7 @@ final class RegistryManagerTests: XCTestCase { var topicToInvitationPubKeyStore: CodableStore! var registry: Registry! var kms: KeyManagementServiceMock! - + override func setUp() { registry = KeyValueRegistry() networkingInteractor = NetworkingInteractorMock() @@ -24,7 +24,7 @@ final class RegistryManagerTests: XCTestCase { logger: ConsoleLoggerMock(), topicToInvitationPubKeyStore: topicToInvitationPubKeyStore) } - + func testRegister() async { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! try! await registryManager.register(account: account) @@ -34,4 +34,3 @@ final class RegistryManagerTests: XCTestCase { XCTAssertFalse(topicToInvitationPubKeyStore.getAll().isEmpty, "stores topic to invitation") } } - diff --git a/Tests/CommonsTests/AnyCodableTests.swift b/Tests/CommonsTests/AnyCodableTests.swift index bdf47dccc..05f42c9f2 100644 --- a/Tests/CommonsTests/AnyCodableTests.swift +++ b/Tests/CommonsTests/AnyCodableTests.swift @@ -2,18 +2,18 @@ import XCTest import TestingUtils @testable import Commons -fileprivate struct SampleStruct: Codable, Equatable { - +private struct SampleStruct: Codable, Equatable { + let bool: Bool let int: Int let double: Double let string: String let object: SubObject? - + struct SubObject: Codable, Equatable { let string: String } - + static func stubRandom() -> SampleStruct { SampleStruct( bool: Bool.random(), @@ -23,7 +23,7 @@ fileprivate struct SampleStruct: Codable, Equatable { object: SubObject(string: UUID().uuidString) ) } - + static func stubFixed() -> SampleStruct { SampleStruct( bool: true, @@ -35,7 +35,7 @@ fileprivate struct SampleStruct: Codable, Equatable { ) ) } - + static let sampleJSONData = """ { "bool": true, @@ -47,7 +47,7 @@ fileprivate struct SampleStruct: Codable, Equatable { } } """.data(using: .utf8)! - + static let invalidJSONData = """ { "bool": ****, @@ -58,7 +58,7 @@ fileprivate struct SampleStruct: Codable, Equatable { """.data(using: .utf8)! } -fileprivate let heterogeneousArrayJSON = """ +private let heterogeneousArrayJSON = """ [ 420, 3.14, @@ -72,7 +72,7 @@ fileprivate let heterogeneousArrayJSON = """ """.data(using: .utf8)! final class AnyCodableTests: XCTestCase { - + func testInitGet() throws { XCTAssertNoThrow(try AnyCodable(Int.random(in: Int.min...Int.max)).get(Int.self)) XCTAssertNoThrow(try AnyCodable(Double.pi).get(Double.self)) @@ -81,7 +81,7 @@ final class AnyCodableTests: XCTestCase { XCTAssertNoThrow(try AnyCodable((1...10).map { _ in UUID().uuidString }).get([String].self)) XCTAssertNoThrow(try AnyCodable(SampleStruct.stubRandom()).get(SampleStruct.self)) } - + func testEqualityInt() { let int = Int.random() let intA = AnyCodable(int) @@ -91,26 +91,26 @@ final class AnyCodableTests: XCTestCase { XCTAssertNotEqual(intA, intC) XCTAssertNotEqual(intB, intC) } - + func testEqualityObject() { let a = AnyCodable(SampleStruct.stubRandom()) let b = AnyCodable(SampleStruct.stubRandom()) XCTAssertEqual(a, a) XCTAssertNotEqual(a, b) } - + func testEqualityEmptyObject() { let a = AnyCodable(EmptyCodable()) let b = AnyCodable(EmptyCodable()) XCTAssertEqual(a, b) } - + func testEqualityFailIfCodingFails() { let a = AnyCodable(FailableCodable()) let b = AnyCodable(FailableCodable()) XCTAssertNotEqual(a, b) } - + func testTwoWayDataRepresentation() throws { let fromInit = AnyCodable(SampleStruct.stubFixed()) let fromJSON = try JSONDecoder().decode(AnyCodable.self, from: SampleStruct.sampleJSONData) @@ -121,7 +121,7 @@ final class AnyCodableTests: XCTestCase { XCTAssertEqual(fromInit, fromJSON, "An AnyCodable initialized both ways with the same data must have a consistent representation.") XCTAssertEqual(encodedFromInit, encodedFromJSON, "Encoded JSON (with sorted keys) must be the same.") } - + func testCodingBool() { [true, false].forEach { bool in do { @@ -135,7 +135,7 @@ final class AnyCodableTests: XCTestCase { } } } - + func testCodingInt() { do { let int = Int.random() @@ -148,7 +148,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testCodingDouble() { do { let double = Double.pi // Value is constant to workaround a JSONDecoder bug: https://bugs.swift.org/browse/SR-7054 @@ -161,7 +161,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testCodingString() { do { let string = UUID().uuidString @@ -174,7 +174,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testCodingArray() { do { let array = (1...10).map { _ in UUID().uuidString } @@ -187,7 +187,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testCodingStruct() { do { let object = SampleStruct.stubRandom() @@ -200,7 +200,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testCodingStructArray() { do { let objects = (1...10).map { _ in SampleStruct.stubRandom() } @@ -213,7 +213,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testDecodingObject() { do { let data = SampleStruct.sampleJSONData @@ -224,7 +224,7 @@ final class AnyCodableTests: XCTestCase { XCTFail() } } - + func testDecodingHeterogeneousArray() throws { let decoded = try JSONDecoder().decode(AnyCodable.self, from: heterogeneousArrayJSON) let array = try decoded.get([AnyCodable].self) @@ -235,7 +235,7 @@ final class AnyCodableTests: XCTestCase { XCTAssertNoThrow(try array[4].get([Int].self)) XCTAssertNoThrow(try array[5].get([String: String].self)) } - + func testDecodeFail() { let data = SampleStruct.invalidJSONData XCTAssertThrowsError(try JSONDecoder().decode(AnyCodable.self, from: data)) { error in diff --git a/Tests/IntegrationTests/ClientDelegate.swift b/Tests/IntegrationTests/ClientDelegate.swift index f1ddb5003..b048db4f8 100644 --- a/Tests/IntegrationTests/ClientDelegate.swift +++ b/Tests/IntegrationTests/ClientDelegate.swift @@ -1,4 +1,3 @@ - import Foundation @testable import WalletConnectSign @@ -6,26 +5,26 @@ class ClientDelegate: SignClientDelegate { func didChangeSocketConnectionStatus(_ status: SocketConnectionStatus) { onConnected?() } - + var client: SignClient - var onSessionSettled: ((Session)->())? - var onConnected: (()->())? - var onSessionProposal: ((Session.Proposal)->())? - var onSessionRequest: ((Request)->())? - var onSessionResponse: ((Response)->())? - var onSessionRejected: ((Session.Proposal, Reason)->())? - var onSessionDelete: (()->())? - var onSessionUpdateNamespaces: ((String, [String : SessionNamespace])->())? - var onSessionUpdateEvents: ((String, Set)->())? - var onSessionExtend: ((String, Date)->())? - var onEventReceived: ((Session.Event, String)->())? - var onPairingUpdate: ((Pairing)->())? - + var onSessionSettled: ((Session) -> Void)? + var onConnected: (() -> Void)? + var onSessionProposal: ((Session.Proposal) -> Void)? + var onSessionRequest: ((Request) -> Void)? + var onSessionResponse: ((Response) -> Void)? + var onSessionRejected: ((Session.Proposal, Reason) -> Void)? + var onSessionDelete: (() -> Void)? + var onSessionUpdateNamespaces: ((String, [String: SessionNamespace]) -> Void)? + var onSessionUpdateEvents: ((String, Set) -> Void)? + var onSessionExtend: ((String, Date) -> Void)? + var onEventReceived: ((Session.Event, String) -> Void)? + var onPairingUpdate: ((Pairing) -> Void)? + internal init(client: SignClient) { self.client = client client.delegate = self } - + func didReject(proposal: Session.Proposal, reason: Reason) { onSessionRejected?(proposal, reason) } @@ -41,7 +40,7 @@ class ClientDelegate: SignClientDelegate { func didDelete(sessionTopic: String, reason: Reason) { onSessionDelete?() } - func didUpdate(sessionTopic: String, namespaces: [String : SessionNamespace]) { + func didUpdate(sessionTopic: String, namespaces: [String: SessionNamespace]) { onSessionUpdateNamespaces?(sessionTopic, namespaces) } func didExtend(sessionTopic: String, to date: Date) { diff --git a/Tests/IntegrationTests/SerialiserTests.swift b/Tests/IntegrationTests/SerialiserTests.swift index 7bbd49e88..93da758d5 100644 --- a/Tests/IntegrationTests/SerialiserTests.swift +++ b/Tests/IntegrationTests/SerialiserTests.swift @@ -8,16 +8,16 @@ import XCTest final class SerializerTests: XCTestCase { var serializer: Serializer! var kms: KeyManagementServiceProtocol! - + override func setUp() { self.kms = KeyManagementServiceMock() self.serializer = Serializer(kms: kms) } - + override func tearDown() { serializer = nil } - + // TODO - change pairing serialisation for sessions func testSerializeDeserialize() { let topic = TopicGenerator().topic @@ -28,4 +28,3 @@ final class SerializerTests: XCTestCase { XCTAssertEqual(messageToSerialize, deserializedMessage) } } - diff --git a/Tests/IntegrationTests/SignClientTests.swift b/Tests/IntegrationTests/SignClientTests.swift index 1d7e4e2bf..313600b1b 100644 --- a/Tests/IntegrationTests/SignClientTests.swift +++ b/Tests/IntegrationTests/SignClientTests.swift @@ -27,7 +27,7 @@ final class SignClientTests: XCTestCase { keyValueStorage: RuntimeKeyValueStorage()) return ClientDelegate(client: client) } - + private func listenForConnection() async { let group = DispatchGroup() group.enter() @@ -41,18 +41,18 @@ final class SignClientTests: XCTestCase { group.wait() return } - + override func setUp() async throws { proposer = Self.makeClientDelegate(name: "🍏P") responder = Self.makeClientDelegate(name: "🍎R") await listenForConnection() } - + override func tearDown() { proposer = nil responder = nil } - + func testSessionPropose() async throws { let dapp = proposer! let wallet = responder! @@ -60,11 +60,10 @@ final class SignClientTests: XCTestCase { let walletSettlementExpectation = expectation(description: "Wallet expects to settle a session") let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - + wallet.onSessionProposal = { proposal in Task { - do { try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - catch { XCTFail("\(error)") } + do { try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } } dapp.onSessionSettled = { _ in @@ -73,12 +72,12 @@ final class SignClientTests: XCTestCase { wallet.onSessionSettled = { _ in walletSettlementExpectation.fulfill() } - + let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces) try await wallet.client.pair(uri: uri!) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: defaultTimeout) } - + func testSessionReject() async throws { let dapp = proposer! let wallet = responder! @@ -86,10 +85,10 @@ final class SignClientTests: XCTestCase { class Store { var rejectedProposal: Session.Proposal? } let store = Store() - + let uri = try await dapp.client.connect(requiredNamespaces: ProposalNamespace.stubRequired()) try await wallet.client.pair(uri: uri!) - + wallet.onSessionProposal = { proposal in Task { do { @@ -352,17 +351,17 @@ final class SignClientTests: XCTestCase { // } } -//public struct EthSendTransaction: Codable, Equatable { +// public struct EthSendTransaction: Codable, Equatable { // public let from: String // public let data: String // public let value: String // public let to: String // public let gasPrice: String // public let nonce: String -//} +// } // // -//fileprivate let ethSendTransaction = """ +// fileprivate let ethSendTransaction = """ // { // "from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155", // "to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567", @@ -372,6 +371,5 @@ final class SignClientTests: XCTestCase { // "value":"0x9184e72a", // "nonce":"0x117" // } -//""" +// """ // - diff --git a/Tests/IntegrationTests/XCTestManifests.swift b/Tests/IntegrationTests/XCTestManifests.swift index 47130fc89..46b3e3788 100644 --- a/Tests/IntegrationTests/XCTestManifests.swift +++ b/Tests/IntegrationTests/XCTestManifests.swift @@ -3,7 +3,7 @@ import XCTest #if !canImport(ObjectiveC) public func allTests() -> [XCTestCaseEntry] { return [ - testCase(IntegrationTests.allTests), + testCase(IntegrationTests.allTests) ] } #endif diff --git a/Tests/JSONRPCTests/Data/RequestJSON.swift b/Tests/JSONRPCTests/Data/RequestJSON.swift index 96b59a40e..8b2f3a483 100644 --- a/Tests/JSONRPCTests/Data/RequestJSON.swift +++ b/Tests/JSONRPCTests/Data/RequestJSON.swift @@ -1,7 +1,7 @@ // MARK: - Valid Request Data enum RequestJSON { - + static let paramsByPosition = """ { "jsonrpc": "2.0", @@ -14,7 +14,7 @@ enum RequestJSON { "id": 1 } """.data(using: .utf8)! - + static let paramsByName = """ { "jsonrpc": "2.0", @@ -27,7 +27,7 @@ enum RequestJSON { "id": 1 } """.data(using: .utf8)! - + static let emptyParamsByPosition = """ { "jsonrpc": "2.0", @@ -36,7 +36,7 @@ enum RequestJSON { "id": 1 } """.data(using: .utf8)! - + static let emptyParamsByName = """ { "jsonrpc": "2.0", @@ -45,7 +45,7 @@ enum RequestJSON { "id": 1 } """.data(using: .utf8)! - + static let paramsOmitted = """ { "jsonrpc": "2.0", @@ -53,7 +53,7 @@ enum RequestJSON { "id": 1 } """.data(using: .utf8)! - + static let withStringIdentifier = """ { "jsonrpc": "2.0", @@ -64,7 +64,7 @@ enum RequestJSON { "id": "a1b2c3d4e5f6" } """.data(using: .utf8)! - + static let notification = """ { "jsonrpc": "2.0", @@ -74,7 +74,7 @@ enum RequestJSON { } } """.data(using: .utf8)! - + static let notificationWithoutParams = """ { "jsonrpc": "2.0", @@ -86,7 +86,7 @@ enum RequestJSON { // MARK: - Invalid Request Data enum InvalidRequestJSON { - + static let badVersion = """ { "jsonrpc": "1.0", @@ -97,7 +97,7 @@ enum InvalidRequestJSON { "id": 1 } """.data(using: .utf8)! - + static let intPrimitiveParams = """ { "jsonrpc": "2.0", @@ -106,7 +106,7 @@ enum InvalidRequestJSON { "id": 1 } """.data(using: .utf8)! - + static let stringPrimitiveParams = """ { "jsonrpc": "2.0", @@ -115,7 +115,7 @@ enum InvalidRequestJSON { "id": 1 } """.data(using: .utf8)! - + static let boolPrimitiveParams = """ { "jsonrpc": "2.0", diff --git a/Tests/JSONRPCTests/Data/ResponseJSON.swift b/Tests/JSONRPCTests/Data/ResponseJSON.swift index bf4deb642..77344e54d 100644 --- a/Tests/JSONRPCTests/Data/ResponseJSON.swift +++ b/Tests/JSONRPCTests/Data/ResponseJSON.swift @@ -1,9 +1,9 @@ // MARK: - Valid Response Data enum ResponseJSON { - + // MARK: - Success Responses - + static let intResult = """ { "jsonrpc": "2.0", @@ -11,7 +11,7 @@ enum ResponseJSON { "id": 1 } """.data(using: .utf8)! - + static let doubleResult = """ { "jsonrpc": "2.0", @@ -19,7 +19,7 @@ enum ResponseJSON { "id": 1 } """.data(using: .utf8)! - + static let stringResult = """ { "id": 1, @@ -27,7 +27,7 @@ enum ResponseJSON { "result": "0xdeadbeef" } """.data(using: .utf8)! - + static let boolResult = """ { "jsonrpc": "2.0", @@ -35,7 +35,7 @@ enum ResponseJSON { "id": 1 } """.data(using: .utf8)! - + static let arrayResult = """ { "id": 1, @@ -45,7 +45,7 @@ enum ResponseJSON { ] } """.data(using: .utf8)! - + static let objectResult = """ { "id": 1, @@ -57,7 +57,7 @@ enum ResponseJSON { } } """.data(using: .utf8)! - + static let withStringIdentifier = """ { "jsonrpc": "2.0", @@ -65,9 +65,9 @@ enum ResponseJSON { "id": "0xdeadbeef" } """.data(using: .utf8)! - + // MARK: - Error Responses - + static let plainError = """ { "jsonrpc": "2.0", @@ -78,7 +78,7 @@ enum ResponseJSON { "id": 0 } """.data(using: .utf8)! - + static let errorWithExplicitNullIdentifier = """ { "jsonrpc": "2.0", @@ -89,7 +89,7 @@ enum ResponseJSON { "id": null } """.data(using: .utf8)! - + static let errorWithImplicitNullIdentifier = """ { "jsonrpc": "2.0", @@ -99,7 +99,7 @@ enum ResponseJSON { } } """.data(using: .utf8)! - + static let errorWithPrimitiveData = """ { "jsonrpc": "2.0", @@ -111,7 +111,7 @@ enum ResponseJSON { "id": 0 } """.data(using: .utf8)! - + static let errorWithStructuredData = """ { "jsonrpc": "2.0", @@ -132,7 +132,7 @@ enum ResponseJSON { // MARK: - Invalid Response Data enum InvalidResponseJSON { - + static let ambiguousResult = """ { "id": 1, @@ -144,14 +144,14 @@ enum InvalidResponseJSON { } } """.data(using: .utf8)! - + static let absentResult = """ { "id": 1, "jsonrpc": "2.0" } """.data(using: .utf8)! - + static let badVersion = """ { "id": 1, @@ -159,7 +159,7 @@ enum InvalidResponseJSON { "result": true } """.data(using: .utf8)! - + static let successWithoutIdentifier = """ { "jsonrpc": "2.0", diff --git a/Tests/JSONRPCTests/Helpers.swift b/Tests/JSONRPCTests/Helpers.swift index c5223270d..9ffc0b45c 100644 --- a/Tests/JSONRPCTests/Helpers.swift +++ b/Tests/JSONRPCTests/Helpers.swift @@ -2,20 +2,20 @@ import Commons @testable import JSONRPC final class TestIdentifierGenerator: IdentifierGenerator { - + var id: RPCID = .right(Int.random()) - + func next() -> RPCID { return id } } extension Either where L == String, R == Int { - + var isString: Bool { left != nil } - + var isNumber: Bool { right != nil } diff --git a/Tests/JSONRPCTests/RPCRequestTests.swift b/Tests/JSONRPCTests/RPCRequestTests.swift index 9f2f878b5..be2460bee 100644 --- a/Tests/JSONRPCTests/RPCRequestTests.swift +++ b/Tests/JSONRPCTests/RPCRequestTests.swift @@ -3,7 +3,7 @@ import Commons import TestingUtils @testable import JSONRPC -fileprivate func makeRequests() -> [RPCRequest] { +private func makeRequests() -> [RPCRequest] { return [ RPCRequest(method: String.random(), id: Int.random()), RPCRequest(method: String.random(), id: String.random()), @@ -16,7 +16,7 @@ fileprivate func makeRequests() -> [RPCRequest] { ] } -fileprivate func makeNotificationRequests() -> [RPCRequest] { +private func makeNotificationRequests() -> [RPCRequest] { return [ RPCRequest.notification(method: String.random()), RPCRequest.notification(method: String.random(), params: EmptyCodable()) @@ -24,7 +24,7 @@ fileprivate func makeNotificationRequests() -> [RPCRequest] { } final class RPCRequestTests: XCTestCase { - + func testIdentifierGeneration() { let idGenerator = TestIdentifierGenerator() let cachedGenerator = RPCRequest.defaultIdentifierGenerator @@ -35,7 +35,7 @@ final class RPCRequestTests: XCTestCase { XCTAssertEqual(requestB.id, idGenerator.id) RPCRequest.defaultIdentifierGenerator = cachedGenerator } - + func testCheckedParamsInit() { XCTAssertNoThrow(try RPCRequest(method: "method", checkedParams: [0])) XCTAssertNoThrow(try RPCRequest(method: "method", checkedParams: [0], id: Int.random())) @@ -44,7 +44,7 @@ final class RPCRequestTests: XCTestCase { XCTAssertNoThrow(try RPCRequest(method: "method", checkedParams: EmptyCodable(), id: Int.random())) XCTAssertNoThrow(try RPCRequest(method: "method", checkedParams: EmptyCodable(), id: String.random())) } - + func testCheckedParamsInitFailsWithPrimitives() { XCTAssertThrowsError(try RPCRequest(method: "method", checkedParams: 0, id: Int.random())) XCTAssertThrowsError(try RPCRequest(method: "method", checkedParams: 0, id: String.random())) @@ -55,7 +55,7 @@ final class RPCRequestTests: XCTestCase { XCTAssertThrowsError(try RPCRequest(method: "method", checkedParams: true, id: Int.random())) XCTAssertThrowsError(try RPCRequest(method: "method", checkedParams: true, id: String.random())) } - + func testRoundTripCoding() throws { let requests = makeRequests() try requests.forEach { request in @@ -66,7 +66,7 @@ final class RPCRequestTests: XCTestCase { XCTAssertFalse(request.isNotification) } } - + func testNotificationRoundTrip() throws { let requests = makeNotificationRequests() try requests.forEach { request in @@ -77,57 +77,57 @@ final class RPCRequestTests: XCTestCase { XCTAssertTrue(request.isNotification) } } - + func testDecodeParamsByPosition() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.paramsByPosition) XCTAssertNotNil(request.params) XCTAssertNotNil(request.id) } - + func testDecodeParamsByName() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.paramsByName) XCTAssertNotNil(request.params) XCTAssertNotNil(request.id) } - + func testDecodeParamsByPositionEmpty() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.emptyParamsByPosition) XCTAssertNotNil(request.params) XCTAssertNotNil(request.id) } - + func testDecodeParamsByNameEmpty() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.emptyParamsByName) XCTAssertNotNil(request.params) XCTAssertNotNil(request.id) } - + func testDecodeOmittedParams() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.paramsOmitted) XCTAssertNil(request.params) XCTAssertNotNil(request.id) } - + func testDecodeRequestIdentifier() throws { let numberRequestId = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.paramsByPosition).id XCTAssert(numberRequestId?.isNumber == true) let stringRequestId = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.withStringIdentifier).id XCTAssert(stringRequestId?.isString == true) } - + func testDecodeNotification() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.notification) XCTAssertNil(request.id) XCTAssertNotNil(request.params) - + } - + func testDecodeNotificationWithoutParams() throws { let request = try JSONDecoder().decode(RPCRequest.self, from: RequestJSON.notificationWithoutParams) XCTAssertNil(request.id) XCTAssertNil(request.params) } - + func testInvalidRequestDecode() { XCTAssertThrowsError(try JSONDecoder().decode(RPCRequest.self, from: InvalidRequestJSON.badVersion)) XCTAssertThrowsError(try JSONDecoder().decode(RPCRequest.self, from: InvalidRequestJSON.intPrimitiveParams)) diff --git a/Tests/JSONRPCTests/RPCResponseTests.swift b/Tests/JSONRPCTests/RPCResponseTests.swift index 454d9af04..954dcc322 100644 --- a/Tests/JSONRPCTests/RPCResponseTests.swift +++ b/Tests/JSONRPCTests/RPCResponseTests.swift @@ -3,7 +3,7 @@ import Commons import TestingUtils @testable import JSONRPC -fileprivate func makeResultResponses() -> [RPCResponse] { +private func makeResultResponses() -> [RPCResponse] { return [ RPCResponse(id: Int.random(), result: Int.random()), RPCResponse(id: Int.random(), result: Bool.random()), @@ -14,7 +14,7 @@ fileprivate func makeResultResponses() -> [RPCResponse] { ] } -fileprivate func makeErrorResponses() -> [RPCResponse] { +private func makeErrorResponses() -> [RPCResponse] { return [ RPCResponse(id: Int.random(), error: JSONRPCError.stub()), RPCResponse(id: String.random(), error: JSONRPCError.stub(data: AnyCodable(Int.random()))), @@ -26,7 +26,7 @@ fileprivate func makeErrorResponses() -> [RPCResponse] { final class RPCResponseTests: XCTestCase { // MARK: - Init & Codable Tests - + func testInitWithResult() { let responses = makeResultResponses() responses.forEach { response in @@ -36,7 +36,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNil(response.error) } } - + func testInitWithError() { let responses = makeErrorResponses() responses.forEach { response in @@ -46,7 +46,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.error) } } - + func testRoundTripResultCoding() throws { let responses = makeResultResponses() try responses.forEach { response in @@ -55,7 +55,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertEqual(decoded, response) } } - + func testRoundTripErrorCoding() throws { let responses = makeErrorResponses() try responses.forEach { response in @@ -64,7 +64,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertEqual(decoded, response) } } - + func testNullIdentifierError() throws { let response = RPCResponse(errorWithoutID: JSONRPCError.stub()) XCTAssertEqual(response.jsonrpc, "2.0") @@ -75,9 +75,9 @@ final class RPCResponseTests: XCTestCase { let decoded = try JSONDecoder().decode(RPCResponse.self, from: encoded) XCTAssertEqual(decoded, response) } - + // MARK: - Decode Result Tests - + func testDecodeResultInt() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.intResult) let intValue = try response.result?.get(Int.self) @@ -85,7 +85,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.id) XCTAssertNil(response.error) } - + func testDecodeResultDouble() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.doubleResult) let doubleValue = try response.result?.get(Double.self) ?? 0.0 @@ -93,7 +93,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.id) XCTAssertNil(response.error) } - + func testDecodeResultString() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.stringResult) let stringValue = try response.result?.get(String.self) @@ -101,7 +101,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.id) XCTAssertNil(response.error) } - + func testDecodeResultBool() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.boolResult) let boolValue = try response.result?.get(Bool.self) @@ -109,7 +109,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.id) XCTAssertNil(response.error) } - + func testDecodeResultArray() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.arrayResult) let arrayValue = try response.result?.get([String].self) @@ -117,7 +117,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(response.id) XCTAssertNil(response.error) } - + func testDecodeResultObject() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.objectResult) let objectValue = try response.result?.get([String: AnyCodable].self) @@ -127,7 +127,7 @@ final class RPCResponseTests: XCTestCase { XCTAssertEqual(try? objectValue?["bool"]?.get(Bool.self), false) XCTAssertEqual(try? objectValue?["string"]?.get(String.self), "0xc0ffee") } - + func testDecodeResponseIdentifier() throws { let numberResponseId = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.intResult).id XCTAssert(numberResponseId?.isNumber == true) @@ -141,16 +141,16 @@ final class RPCResponseTests: XCTestCase { let implicitNullResponseId = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.errorWithImplicitNullIdentifier).id XCTAssertNil(implicitNullResponseId) } - + // MARK: - Decode Error Tests - + func testDecodeError() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.plainError) XCTAssertNil(response.result) XCTAssertNotNil(response.error) XCTAssertEqual(response.error?.code, -32600) } - + func testDecodeErrorWithPrimitiveData() throws { let response = try JSONDecoder().decode(RPCResponse.self, from: ResponseJSON.errorWithPrimitiveData) XCTAssertNil(response.result) @@ -167,9 +167,9 @@ final class RPCResponseTests: XCTestCase { XCTAssertNotNil(try heterogeneousArray?[1].get(Bool.self)) XCTAssertNotNil(try heterogeneousArray?[2].get(String.self)) } - + // MARK: - Invalid Data Tests - + func testInvalidResponseDecode() { XCTAssertThrowsError(try JSONDecoder().decode(RPCResponse.self, from: InvalidResponseJSON.ambiguousResult), "A response must not include both result and error members.") XCTAssertThrowsError(try JSONDecoder().decode(RPCResponse.self, from: InvalidResponseJSON.absentResult), "A response must include either a result or an error member.") diff --git a/Tests/RelayerTests/AutomaticSocketConnectionHandlerTests.swift b/Tests/RelayerTests/AutomaticSocketConnectionHandlerTests.swift index 395f2a7c5..ad3795149 100644 --- a/Tests/RelayerTests/AutomaticSocketConnectionHandlerTests.swift +++ b/Tests/RelayerTests/AutomaticSocketConnectionHandlerTests.swift @@ -1,4 +1,3 @@ - import Foundation import XCTest @testable import WalletConnectRelay @@ -27,7 +26,7 @@ final class AutomaticSocketConnectionHandlerTests: XCTestCase { networkMonitor.onSatisfied?() XCTAssertTrue(sut.socket.isConnected) } - + func testHandleConnectThrows() { XCTAssertThrowsError(try sut.handleConnect()) } @@ -35,19 +34,19 @@ final class AutomaticSocketConnectionHandlerTests: XCTestCase { func testHandleDisconnectThrows() { XCTAssertThrowsError(try sut.handleDisconnect(closeCode: .normalClosure)) } - + func testReconnectsOnEnterForeground() { webSocketSession.disconnect() appStateObserver.onWillEnterForeground?() XCTAssertTrue(sut.socket.isConnected) } - + func testRegisterTaskOnEnterBackground() { XCTAssertNil(backgroundTaskRegistrar.completion) appStateObserver.onWillEnterBackground?() XCTAssertNotNil(backgroundTaskRegistrar.completion) } - + func testDisconnectOnEndBackgroundTask() { appStateObserver.onWillEnterBackground?() XCTAssertTrue(sut.socket.isConnected) diff --git a/Tests/RelayerTests/DispatcherTests.swift b/Tests/RelayerTests/DispatcherTests.swift index 2e716f4d2..ab9cd914c 100644 --- a/Tests/RelayerTests/DispatcherTests.swift +++ b/Tests/RelayerTests/DispatcherTests.swift @@ -1,14 +1,12 @@ - import Foundation import XCTest @testable import WalletConnectRelay import TestingUtils - class WebSocketMock: WebSocketProtocol, WebSocketConnecting { - var onText: ((String) -> ())? - var onConnect: (() -> ())? - var onDisconnect: ((Error?) -> ())? + var onText: ((String) -> Void)? + var onConnect: (() -> Void)? + var onDisconnect: ((Error?) -> Void)? var sendCallCount: Int = 0 var isConnected: Bool = false @@ -22,7 +20,7 @@ class WebSocketMock: WebSocketProtocol, WebSocketConnecting { onDisconnect?(nil) } - func write(string: String, completion: (() -> ())?) { + func write(string: String, completion: (() -> Void)?) { sendCallCount+=1 } } @@ -39,7 +37,7 @@ final class DispatcherTests: XCTestCase { func testSendWhileConnected() { try! sut.connect() - sut.send("1"){_ in} + sut.send("1") {_ in} XCTAssertEqual(webSocket.sendCallCount, 1) } diff --git a/Tests/RelayerTests/Helpers/Error+Extension.swift b/Tests/RelayerTests/Helpers/Error+Extension.swift index efc848317..f0bdc18e3 100644 --- a/Tests/RelayerTests/Helpers/Error+Extension.swift +++ b/Tests/RelayerTests/Helpers/Error+Extension.swift @@ -2,14 +2,14 @@ import Foundation @testable import WalletConnectRelay extension NSError { - + static func mock(code: Int = -9999) -> NSError { NSError(domain: "com.walletconnect.sdk.tests.error", code: code, userInfo: nil) } } extension Error { - + var asNetworkError: NetworkError? { return self as? NetworkError } @@ -21,12 +21,12 @@ extension NetworkError { guard case .webSocketNotConnected = self else { return false } return true } - + var isSendMessageError: Bool { guard case .sendMessageFailed = self else { return false } return true } - + var isReceiveMessageError: Bool { guard case .receiveMessageFailure = self else { return false } return true diff --git a/Tests/RelayerTests/Helpers/URL+Extension.swift b/Tests/RelayerTests/Helpers/URL+Extension.swift index 273178314..03787daa4 100644 --- a/Tests/RelayerTests/Helpers/URL+Extension.swift +++ b/Tests/RelayerTests/Helpers/URL+Extension.swift @@ -1,7 +1,7 @@ import Foundation extension URL { - + static func stub() -> URL { URL(string: "https://httpbin.org")! } diff --git a/Tests/RelayerTests/ManualSocketConnectionHandlerTests.swift b/Tests/RelayerTests/ManualSocketConnectionHandlerTests.swift index 994042b2d..0b809b918 100644 --- a/Tests/RelayerTests/ManualSocketConnectionHandlerTests.swift +++ b/Tests/RelayerTests/ManualSocketConnectionHandlerTests.swift @@ -1,5 +1,3 @@ - - import Foundation import XCTest @testable import WalletConnectRelay @@ -12,14 +10,14 @@ final class ManualSocketConnectionHandlerTests: XCTestCase { socket = WebSocketMock() sut = ManualSocketConnectionHandler(socket: socket) } - + func testHandleDisconnect() { socket.connect() XCTAssertTrue(socket.isConnected) try! sut.handleDisconnect(closeCode: .normalClosure) XCTAssertFalse(socket.isConnected) } - + func testHandleConnect() { XCTAssertFalse(socket.isConnected) try! sut.handleConnect() diff --git a/Tests/RelayerTests/Mocks/AppStateObserverMock.swift b/Tests/RelayerTests/Mocks/AppStateObserverMock.swift index e11d6af38..5eb39c927 100644 --- a/Tests/RelayerTests/Mocks/AppStateObserverMock.swift +++ b/Tests/RelayerTests/Mocks/AppStateObserverMock.swift @@ -1,8 +1,7 @@ - import Foundation @testable import WalletConnectRelay class AppStateObserverMock: AppStateObserving { - var onWillEnterForeground: (() -> ())? - var onWillEnterBackground: (() -> ())? + var onWillEnterForeground: (() -> Void)? + var onWillEnterBackground: (() -> Void)? } diff --git a/Tests/RelayerTests/Mocks/BackgroundTaskRegistrarMock.swift b/Tests/RelayerTests/Mocks/BackgroundTaskRegistrarMock.swift index 0418155d9..d13eefefb 100644 --- a/Tests/RelayerTests/Mocks/BackgroundTaskRegistrarMock.swift +++ b/Tests/RelayerTests/Mocks/BackgroundTaskRegistrarMock.swift @@ -1,10 +1,9 @@ - import Foundation @testable import WalletConnectRelay class BackgroundTaskRegistrarMock: BackgroundTaskRegistering { - var completion: (()->())? - func register(name: String, completion: @escaping () -> ()) { + var completion: (() -> Void)? + func register(name: String, completion: @escaping () -> Void) { self.completion = completion } } diff --git a/Tests/RelayerTests/Mocks/DispatcherMock.swift b/Tests/RelayerTests/Mocks/DispatcherMock.swift index 4657c3ab6..64afe594e 100644 --- a/Tests/RelayerTests/Mocks/DispatcherMock.swift +++ b/Tests/RelayerTests/Mocks/DispatcherMock.swift @@ -4,11 +4,11 @@ import Foundation @testable import WalletConnectRelay class DispatcherMock: Dispatching { - var onConnect: (() -> ())? - var onDisconnect: (() -> ())? - var onMessage: ((String) -> ())? + var onConnect: (() -> Void)? + var onDisconnect: (() -> Void)? + var onMessage: ((String) -> Void)? var sent = false - func send(_ string: String, completion: @escaping (Error?) -> ()) { + func send(_ string: String, completion: @escaping (Error?) -> Void) { sent = true } func send(_ string: String) async throws { diff --git a/Tests/RelayerTests/Mocks/NetworkMonitoringMock.swift b/Tests/RelayerTests/Mocks/NetworkMonitoringMock.swift index ce3bb5576..7f6a5245e 100644 --- a/Tests/RelayerTests/Mocks/NetworkMonitoringMock.swift +++ b/Tests/RelayerTests/Mocks/NetworkMonitoringMock.swift @@ -1,10 +1,9 @@ - import Foundation @testable import WalletConnectRelay class NetworkMonitoringMock: NetworkMonitoring { - var onSatisfied: (() -> ())? - var onUnsatisfied: (() -> ())? - + var onSatisfied: (() -> Void)? + var onUnsatisfied: (() -> Void)? + func startMonitoring() { } } diff --git a/Tests/RelayerTests/RelayClientEndToEndTests.swift b/Tests/RelayerTests/RelayClientEndToEndTests.swift index c204a6de9..90a1066b3 100644 --- a/Tests/RelayerTests/RelayClientEndToEndTests.swift +++ b/Tests/RelayerTests/RelayClientEndToEndTests.swift @@ -1,4 +1,3 @@ - import Foundation import Combine import XCTest @@ -8,11 +7,11 @@ import TestingUtils import Starscream final class RelayClientEndToEndTests: XCTestCase { - + let relayHost = "relay.walletconnect.com" let projectId = "8ba9ee138960775e5231b70cc5ef1c3a" private var publishers = [AnyCancellable]() - + func makeRelayClient() -> RelayClient { let logger = ConsoleLogger() let url = RelayClient.makeRelayUrl(host: relayHost, projectId: projectId) @@ -20,7 +19,7 @@ final class RelayClientEndToEndTests: XCTestCase { let dispatcher = Dispatcher(socket: socket, socketConnectionHandler: ManualSocketConnectionHandler(socket: socket), logger: logger) return RelayClient(dispatcher: dispatcher, logger: logger, keyValueStorage: RuntimeKeyValueStorage()) } - + func testSubscribe() { let relayClient = makeRelayClient() try! relayClient.connect() @@ -36,7 +35,7 @@ final class RelayClientEndToEndTests: XCTestCase { }.store(in: &publishers) waitForExpectations(timeout: defaultTimeout, handler: nil) } - + func testEndToEndPayload() { let relayA = makeRelayClient() let relayB = makeRelayClient() @@ -53,7 +52,7 @@ final class RelayClientEndToEndTests: XCTestCase { let expectationA = expectation(description: "publish payloads send and receive successfuly") let expectationB = expectation(description: "publish payloads send and receive successfuly") - + expectationA.assertForOverFulfill = false expectationB.assertForOverFulfill = false @@ -85,8 +84,8 @@ final class RelayClientEndToEndTests: XCTestCase { waitForExpectations(timeout: defaultTimeout, handler: nil) XCTAssertEqual(subscriptionATopic, randomTopic) XCTAssertEqual(subscriptionBTopic, randomTopic) - - //TODO - uncomment lines when request rebound is resolved + + // TODO - uncomment lines when request rebound is resolved // XCTAssertEqual(subscriptionBPayload, payloadA) // XCTAssertEqual(subscriptionAPayload, payloadB) } diff --git a/Tests/RelayerTests/WakuRelayTests.swift b/Tests/RelayerTests/WakuRelayTests.swift index 5e95572b2..da724e27e 100644 --- a/Tests/RelayerTests/WakuRelayTests.swift +++ b/Tests/RelayerTests/WakuRelayTests.swift @@ -1,4 +1,3 @@ - import WalletConnectUtils import Foundation import Combine @@ -19,7 +18,7 @@ class WakuRelayTests: XCTestCase { wakuRelay = nil dispatcher = nil } - + func testNotifyOnSubscriptionRequest() { let subscriptionExpectation = expectation(description: "notifies with encoded message on a waku subscription event") let topic = "0987" @@ -35,7 +34,7 @@ class WakuRelayTests: XCTestCase { dispatcher.onMessage?(try! subscriptionRequest.json()) waitForExpectations(timeout: 0.001, handler: nil) } - + func testPublishRequestAcknowledge() { let acknowledgeExpectation = expectation(description: "completion with no error on waku request acknowledge after publish") let requestId = wakuRelay.publish(topic: "", payload: "{}", onNetworkAcknowledge: { error in @@ -46,7 +45,7 @@ class WakuRelayTests: XCTestCase { dispatcher.onMessage?(response) waitForExpectations(timeout: 0.001, handler: nil) } - + func testUnsubscribeRequestAcknowledge() { let acknowledgeExpectation = expectation(description: "completion with no error on waku request acknowledge after unsubscribe") let topic = "1234" @@ -59,7 +58,7 @@ class WakuRelayTests: XCTestCase { dispatcher.onMessage?(response) waitForExpectations(timeout: 0.001, handler: nil) } - + func testSubscriptionRequestDeliveredOnce() { let expectation = expectation(description: "Request duplicate not delivered") let subscriptionParams = RelayJSONRPC.SubscriptionParams(id: "sub_id", data: RelayJSONRPC.SubscriptionData(topic: "topic", message: "message")) @@ -71,17 +70,17 @@ class WakuRelayTests: XCTestCase { dispatcher.onMessage?(try! subscriptionRequest.json()) waitForExpectations(timeout: 0.001, handler: nil) } - + func testSendOnPublish() { wakuRelay.publish(topic: "", payload: "", onNetworkAcknowledge: { _ in}) XCTAssertTrue(dispatcher.sent) } - + func testSendOnSubscribe() { wakuRelay.subscribe(topic: "") {_ in } XCTAssertTrue(dispatcher.sent) } - + func testSendOnUnsubscribe() { let topic = "123" wakuRelay.subscriptions[topic] = "" @@ -89,4 +88,3 @@ class WakuRelayTests: XCTestCase { XCTAssertTrue(dispatcher.sent) } } - diff --git a/Tests/TestingUtils/ConsoleLoggerMock.swift b/Tests/TestingUtils/ConsoleLoggerMock.swift index df5ba2216..9be922bf1 100644 --- a/Tests/TestingUtils/ConsoleLoggerMock.swift +++ b/Tests/TestingUtils/ConsoleLoggerMock.swift @@ -1,4 +1,3 @@ - import Foundation import WalletConnectUtils diff --git a/Tests/TestingUtils/Helpers.swift b/Tests/TestingUtils/Helpers.swift index 4f1fba530..dbe46147d 100644 --- a/Tests/TestingUtils/Helpers.swift +++ b/Tests/TestingUtils/Helpers.swift @@ -10,7 +10,7 @@ public extension Int { } public extension Double { - + // Do not use this function when testing Codables: https://bugs.swift.org/browse/SR-7054 static func random() -> Double { random(in: 0...1) @@ -18,23 +18,23 @@ public extension Double { } public extension String { - + static func random() -> String { randomTopic() } - + static func randomTopic() -> String { "\(UUID().uuidString)\(UUID().uuidString)".replacingOccurrences(of: "-", with: "").lowercased() } } public extension Result { - + var isSuccess: Bool { if case .success = self { return true } return false } - + var isFailure: Bool { if case .failure = self { return true } return false diff --git a/Tests/TestingUtils/Mocks/KeyManagementServiceMock.swift b/Tests/TestingUtils/Mocks/KeyManagementServiceMock.swift index 0686e0986..e966d080a 100644 --- a/Tests/TestingUtils/Mocks/KeyManagementServiceMock.swift +++ b/Tests/TestingUtils/Mocks/KeyManagementServiceMock.swift @@ -9,32 +9,31 @@ final class KeyManagementServiceMock: KeyManagementServiceProtocol { return try? getSymmetricKey(for: topic)?.rawRepresentation } } - + func createSymmetricKey(_ topic: String) throws -> SymmetricKey { let key = SymmetricKey() try setSymmetricKey(key, for: topic) return key } - + func setSymmetricKey(_ symmetricKey: SymmetricKey, for topic: String) throws { symmetricKeys[topic] = symmetricKey } - + func getSymmetricKey(for topic: String) throws -> SymmetricKey? { symmetricKeys[topic] } - + func deleteSymmetricKey(for topic: String) { symmetricKeys[topic] = nil } - - + func createX25519KeyPair() throws -> AgreementPublicKey { defer { privateKeyStub = AgreementPrivateKey() } try setPrivateKey(privateKeyStub) return privateKeyStub.publicKey } - + func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementKeys { // TODO: Fix mock guard let privateKey = try getPrivateKey(for: selfPublicKey) else { @@ -45,47 +44,46 @@ final class KeyManagementServiceMock: KeyManagementServiceProtocol { let sharedKey = sharedSecret.deriveSymmetricKey() return AgreementKeys(sharedKey: sharedKey, publicKey: privateKey.publicKey) } - - + var privateKeyStub = AgreementPrivateKey() - + private(set) var privateKeys: [String: AgreementPrivateKey] = [:] private(set) var symmetricKeys: [String: SymmetricKey] = [:] private(set) var agreementKeys: [String: AgreementKeys] = [:] - + func makePrivateKey() -> AgreementPrivateKey { defer { privateKeyStub = AgreementPrivateKey() } return privateKeyStub } - + func setPrivateKey(_ privateKey: AgreementPrivateKey) throws { privateKeys[privateKey.publicKey.rawRepresentation.toHexString()] = privateKey } - + func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? { privateKeys[publicKey.rawRepresentation.toHexString()] } - + func getPrivateKey(for publicKey: String) throws -> AgreementPrivateKey? { privateKeys[publicKey] } - + func setAgreementSecret(_ agreementKeys: AgreementKeys, topic: String) { self.agreementKeys[topic] = agreementKeys } - + func getAgreementSecret(for topic: String) -> AgreementKeys? { agreementKeys[topic] } - + func deletePrivateKey(for publicKey: String) { privateKeys[publicKey] = nil } - + func deleteAgreementSecret(for topic: String) { agreementKeys[topic] = nil } - + func deleteAll() throws { privateKeys = [:] symmetricKeys = [:] @@ -94,15 +92,15 @@ final class KeyManagementServiceMock: KeyManagementServiceProtocol { } extension KeyManagementServiceMock { - + func hasPrivateKey(for publicKeyHex: String) -> Bool { privateKeys[publicKeyHex] != nil } - + func hasAgreementSecret(for topic: String) -> Bool { agreementKeys[topic] != nil } - + func hasSymmetricKey(for topic: String) -> Bool { symmetricKeys[topic] != nil } diff --git a/Tests/TestingUtils/Mocks/KeychainServiceFake.swift b/Tests/TestingUtils/Mocks/KeychainServiceFake.swift index 048116c40..abed2d3f5 100644 --- a/Tests/TestingUtils/Mocks/KeychainServiceFake.swift +++ b/Tests/TestingUtils/Mocks/KeychainServiceFake.swift @@ -2,15 +2,15 @@ import Foundation @testable import WalletConnectKMS final public class KeychainServiceFake: KeychainServiceProtocol { - + var errorStatus: OSStatus? - + private var storage: [String: Data] - + public init() { self.storage = [:] } - + public func add(_ attributes: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { if let forceError = errorStatus { return forceError @@ -25,7 +25,7 @@ final public class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + public func copyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { if let forceError = errorStatus { return forceError @@ -40,7 +40,7 @@ final public class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + public func update(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus { if let forceError = errorStatus { return forceError @@ -56,7 +56,7 @@ final public class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + public func delete(_ query: CFDictionary) -> OSStatus { if let forceError = errorStatus { return forceError @@ -77,7 +77,7 @@ final public class KeychainServiceFake: KeychainServiceProtocol { } } } - + private func getKeyAndData(from attributes: CFDictionary) -> (key: String, data: Data)? { let dict = (attributes as NSDictionary) if let data = dict[kSecValueData] as? Data, diff --git a/Tests/TestingUtils/Mocks/KeychainStorageMock.swift b/Tests/TestingUtils/Mocks/KeychainStorageMock.swift index 58bbdc73c..6cc744a3d 100644 --- a/Tests/TestingUtils/Mocks/KeychainStorageMock.swift +++ b/Tests/TestingUtils/Mocks/KeychainStorageMock.swift @@ -2,31 +2,31 @@ import Foundation @testable import WalletConnectKMS final class KeychainStorageMock: KeychainStorageProtocol { - + var storage: [String: Data] = [:] - + private(set) var didCallAdd = false private(set) var didCallRead = false private(set) var didCallDelete = false - - func add(_ item: T, forKey key: String) throws where T : GenericPasswordConvertible { + + func add(_ item: T, forKey key: String) throws where T: GenericPasswordConvertible { didCallAdd = true storage[key] = item.rawRepresentation } - - func read(key: String) throws -> T where T : GenericPasswordConvertible { + + func read(key: String) throws -> T where T: GenericPasswordConvertible { didCallRead = true if let data = storage[key] { return try T(rawRepresentation: data) } throw KeychainError(errSecItemNotFound) } - + func delete(key: String) throws { didCallDelete = true storage[key] = nil } - + func deleteAll() throws { storage = [:] } diff --git a/Tests/TestingUtils/TopicGenerator.swift b/Tests/TestingUtils/TopicGenerator.swift index 9f163945b..501096569 100644 --- a/Tests/TestingUtils/TopicGenerator.swift +++ b/Tests/TestingUtils/TopicGenerator.swift @@ -1,13 +1,13 @@ @testable import WalletConnectUtils public final class TopicGenerator { - + let topic: String - + init(topic: String = String.generateTopic()) { self.topic = topic } - + func getTopic() -> String { return topic } diff --git a/Tests/TestingUtils/XCTest.swift b/Tests/TestingUtils/XCTest.swift index e3048f849..044652c89 100644 --- a/Tests/TestingUtils/XCTest.swift +++ b/Tests/TestingUtils/XCTest.swift @@ -1,4 +1,3 @@ - import Foundation import XCTest @@ -17,7 +16,7 @@ extension XCTest { errorHandler(error) } } - + public func XCTAssertNoThrowAsync( _ expression: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", diff --git a/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift b/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift index 2416bb7a2..aef7cc1be 100644 --- a/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift +++ b/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift @@ -2,7 +2,7 @@ import Foundation @testable import WalletConnectKMS extension AgreementKeys { - + static func stub() -> AgreementKeys { let key = try! SymmetricKey(rawRepresentation: Data.randomBytes(count: 32)) return AgreementKeys(sharedKey: key, publicKey: AgreementPrivateKey().publicKey) diff --git a/Tests/WalletConnectKMSTests/ChaChaPolyCodec_Test.swift b/Tests/WalletConnectKMSTests/ChaChaPolyCodec_Test.swift index 8ada27a55..db8549e85 100644 --- a/Tests/WalletConnectKMSTests/ChaChaPolyCodec_Test.swift +++ b/Tests/WalletConnectKMSTests/ChaChaPolyCodec_Test.swift @@ -1,4 +1,3 @@ - import Foundation import XCTest @testable import WalletConnectKMS @@ -33,9 +32,9 @@ class ChaChaPolyCodec_Test: XCTestCase { let encryptedPayload = try! codec.encode(plaintext: message, symmetricKey: symmetricKey) XCTAssertNoThrow(try codec.decode(sealboxString: encryptedPayload, symmetricKey: symmetricKey)) } - + // MARK: - Tests cohesion with Kotlin and JS - + func testEncodeCohesion() { let plaintext = "WalletConnect" let nonceString = "qwecfaasdads" @@ -43,7 +42,7 @@ class ChaChaPolyCodec_Test: XCTestCase { let serializedMessage = try! codec.encode(plaintext: plaintext, symmetricKey: symmetricKey, nonce: nonce) XCTAssertEqual(serializedMessage, "cXdlY2ZhYXNkYWRzVhkbjHqli8hN0rFbAtMPIsJho4zLvWskMTQKSGw=") } - + func testDecodeCohesion() { let combinedSealBox = "cXdlY2ZhYXNkYWRzVhkbjHqli8hN0rFbAtMPIsJho4zLvWskMTQKSGw=" let decryptedData = try! codec.decode(sealboxString: combinedSealBox, symmetricKey: symmetricKey) diff --git a/Tests/WalletConnectKMSTests/KeyManagementServiceTests.swift b/Tests/WalletConnectKMSTests/KeyManagementServiceTests.swift index 5cba094ef..e50f5c11f 100644 --- a/Tests/WalletConnectKMSTests/KeyManagementServiceTests.swift +++ b/Tests/WalletConnectKMSTests/KeyManagementServiceTests.swift @@ -10,7 +10,7 @@ fileprivate extension Error { } class KeyManagementServiceTests: XCTestCase { - + var kms: KeyManagementService! override func setUp() { @@ -20,14 +20,14 @@ class KeyManagementServiceTests: XCTestCase { override func tearDown() { kms = nil } - + func testCreateKeyPair() throws { let publicKey = try kms.createX25519KeyPair() let privateKey = try kms.getPrivateKey(for: publicKey) XCTAssertNotNil(privateKey) XCTAssertEqual(privateKey?.publicKey, publicKey) } - + func testPrivateKeyRoundTrip() throws { let privateKey = AgreementPrivateKey() let publicKey = privateKey.publicKey @@ -36,7 +36,7 @@ class KeyManagementServiceTests: XCTestCase { let storedPrivateKey = try kms.getPrivateKey(for: publicKey) XCTAssertEqual(privateKey, storedPrivateKey) } - + func testDeletePrivateKey() throws { let privateKey = AgreementPrivateKey() let publicKey = privateKey.publicKey @@ -44,7 +44,7 @@ class KeyManagementServiceTests: XCTestCase { kms.deletePrivateKey(for: publicKey.hexRepresentation) XCTAssertNil(try kms.getPrivateKey(for: publicKey)) } - + func testAgreementSecretRoundTrip() throws { let topic = "topic" XCTAssertNil(try kms.getAgreementSecret(for: topic)) @@ -53,7 +53,7 @@ class KeyManagementServiceTests: XCTestCase { let storedAgreementSecret = try kms.getAgreementSecret(for: topic) XCTAssertEqual(agreementKeys, storedAgreementSecret) } - + func testDeleteAgreementSecret() throws { let topic = "topic" let agreementKeys = AgreementKeys.stub() @@ -61,7 +61,7 @@ class KeyManagementServiceTests: XCTestCase { kms.deleteAgreementSecret(for: topic) XCTAssertNil(try kms.getAgreementSecret(for: topic)) } - + func testGenerateX25519Agreement() throws { let privateKeyA = try AgreementPrivateKey(rawRepresentation: CryptoTestData.privateKeyA) let privateKeyB = try AgreementPrivateKey(rawRepresentation: CryptoTestData.privateKeyB) @@ -71,7 +71,7 @@ class KeyManagementServiceTests: XCTestCase { XCTAssertEqual(agreementSecretA.sharedKey, agreementSecretB.sharedKey) XCTAssertEqual(agreementSecretA.sharedKey.rawRepresentation, CryptoTestData.expectedSharedKey) } - + func testGenerateX25519AgreementRandomKeys() throws { let privateKeyA = AgreementPrivateKey() let privateKeyB = AgreementPrivateKey() @@ -79,7 +79,7 @@ class KeyManagementServiceTests: XCTestCase { let agreementSecretB = try KeyManagementService.generateAgreementKey(from: privateKeyB, peerPublicKey: privateKeyA.publicKey.hexRepresentation) XCTAssertEqual(agreementSecretA.sharedKey, agreementSecretB.sharedKey) } - + func testPerformKeyAgreement() throws { let privateKeySelf = AgreementPrivateKey() let privateKeyPeer = AgreementPrivateKey() @@ -88,7 +88,7 @@ class KeyManagementServiceTests: XCTestCase { let selfSecret = try kms.performKeyAgreement(selfPublicKey: privateKeySelf.publicKey, peerPublicKey: privateKeyPeer.publicKey.hexRepresentation) XCTAssertEqual(selfSecret.sharedKey, peerSecret.sharedKey) } - + func testPerformKeyAgreementFailure() { let publicKeySelf = AgreementPrivateKey().publicKey let publicKeyPeer = AgreementPrivateKey().publicKey.hexRepresentation @@ -96,14 +96,14 @@ class KeyManagementServiceTests: XCTestCase { XCTAssert(error.isKeyNotFoundError) } } - + func testCreateSymmetricKey() { let topic = "topic" let key = try! kms.createSymmetricKey(topic) let retrievedKey = try! kms.getSymmetricKey(for: topic) XCTAssertEqual(key, retrievedKey) } - + func testSymmetricKeyRoundTrip() { let topic = "topic" let key = SymmetricKey() @@ -111,7 +111,7 @@ class KeyManagementServiceTests: XCTestCase { let retrievedKey = try! kms.getSymmetricKey(for: topic) XCTAssertEqual(key, retrievedKey) } - + func testDeleteSymmetricKey() { let topic = "topic" let key = SymmetricKey() diff --git a/Tests/WalletConnectKMSTests/KeychainServiceFake.swift b/Tests/WalletConnectKMSTests/KeychainServiceFake.swift index 49f18d171..49fb82687 100644 --- a/Tests/WalletConnectKMSTests/KeychainServiceFake.swift +++ b/Tests/WalletConnectKMSTests/KeychainServiceFake.swift @@ -2,11 +2,11 @@ import Foundation @testable import WalletConnectKMS final class KeychainServiceFake: KeychainServiceProtocol { - + var errorStatus: OSStatus? - + private var storage: [String: Data] = [:] - + func add(_ attributes: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { if let forceError = errorStatus { return forceError @@ -21,7 +21,7 @@ final class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + func copyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus { if let forceError = errorStatus { return forceError @@ -36,7 +36,7 @@ final class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + func update(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus { if let forceError = errorStatus { return forceError @@ -52,7 +52,7 @@ final class KeychainServiceFake: KeychainServiceProtocol { } return errSecInternalError } - + func delete(_ query: CFDictionary) -> OSStatus { if let forceError = errorStatus { return forceError @@ -73,7 +73,7 @@ final class KeychainServiceFake: KeychainServiceProtocol { } } } - + private func getKeyAndData(from attributes: CFDictionary) -> (key: String, data: Data)? { let dict = (attributes as NSDictionary) if let data = dict[kSecValueData] as? Data, diff --git a/Tests/WalletConnectKMSTests/KeychainStorageTests.swift b/Tests/WalletConnectKMSTests/KeychainStorageTests.swift index be375a427..83ff4e5ca 100644 --- a/Tests/WalletConnectKMSTests/KeychainStorageTests.swift +++ b/Tests/WalletConnectKMSTests/KeychainStorageTests.swift @@ -5,20 +5,20 @@ import CryptoKit extension Curve25519.KeyAgreement.PrivateKey: GenericPasswordConvertible {} final class KeychainStorageTests: XCTestCase { - + var sut: KeychainStorage! - + var fakeKeychain: KeychainServiceFake! - + let defaultIdentifier = "key" - + override func setUp() { fakeKeychain = KeychainServiceFake() sut = KeychainStorage( keychainService: fakeKeychain, serviceIdentifier: "") } - + override func tearDown() { try? sut.deleteAll() sut = nil @@ -30,7 +30,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssertNoThrow(try sut.add(privateKey, forKey: "id-1")) XCTAssertNoThrow(try sut.add(privateKey, forKey: "id-2")) } - + func testAddDuplicateItemError() { let privateKey = Curve25519.KeyAgreement.PrivateKey() try? sut.add(privateKey, forKey: defaultIdentifier) @@ -39,7 +39,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssertEqual(error.status, errSecDuplicateItem) } } - + func testAddUnknownFailure() { fakeKeychain.errorStatus = errSecMissingEntitlement let privateKey = Curve25519.KeyAgreement.PrivateKey() @@ -47,7 +47,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssert(error is KeychainError) } } - + func testRead() { let privateKey = Curve25519.KeyAgreement.PrivateKey() do { @@ -58,7 +58,7 @@ final class KeychainStorageTests: XCTestCase { XCTFail() } } - + func testReadItemNotFoundFails() { do { let _: Curve25519.KeyAgreement.PrivateKey = try sut.read(key: "") @@ -68,7 +68,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssertEqual(error.status, errSecItemNotFound) } } - + func testReadUnknownFailure() { let privateKey = Curve25519.KeyAgreement.PrivateKey() do { @@ -80,7 +80,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssert(error is KeychainError) } } - + func testUpdate() { let privateKeyA = Curve25519.KeyAgreement.PrivateKey() let privateKeyB = Curve25519.KeyAgreement.PrivateKey() @@ -93,7 +93,7 @@ final class KeychainStorageTests: XCTestCase { XCTFail() } } - + func testUpdateItemNotFoundFails() { let privateKey = Curve25519.KeyAgreement.PrivateKey() XCTAssertThrowsError(try sut.update(privateKey, forKey: defaultIdentifier)) { error in @@ -101,7 +101,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssertEqual(error.status, errSecItemNotFound) } } - + func testUpdateUnknownFailure() { let privateKeyA = Curve25519.KeyAgreement.PrivateKey() let privateKeyB = Curve25519.KeyAgreement.PrivateKey() @@ -114,7 +114,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssert(error is KeychainError) } } - + func testDelete() { let privateKey = Curve25519.KeyAgreement.PrivateKey() try? sut.add(privateKey, forKey: defaultIdentifier) @@ -125,11 +125,11 @@ final class KeychainStorageTests: XCTestCase { XCTFail() } } - + func testDeleteNotFoundDoesntThrowError() { XCTAssertNoThrow(try sut.delete(key: defaultIdentifier)) } - + func testDeleteUnknownFailure() { fakeKeychain.errorStatus = errSecMissingEntitlement let privateKey = Curve25519.KeyAgreement.PrivateKey() @@ -141,7 +141,7 @@ final class KeychainStorageTests: XCTestCase { XCTAssert(error is KeychainError) } } - + func testDeleteAll() { do { let keys = (1...10).map { "key-\($0)" } @@ -157,7 +157,7 @@ final class KeychainStorageTests: XCTestCase { XCTFail() } } - + func testDeleteAllFromCleanKeychain() { XCTAssertThrowsError(try sut.deleteAll()) { error in XCTAssert(error is KeychainError) diff --git a/Tests/WalletConnectSignTests/AccountTests.swift b/Tests/WalletConnectSignTests/AccountTests.swift index 3b7127ec8..65d3fcbcb 100644 --- a/Tests/WalletConnectSignTests/AccountTests.swift +++ b/Tests/WalletConnectSignTests/AccountTests.swift @@ -2,58 +2,58 @@ import XCTest @testable import WalletConnectSign final class AccountTests: XCTestCase { - + func testInitFromString() { // Valid accounts XCTAssertNotNil(Account("std:0:0")) XCTAssertNotNil(Account("chainstd:8c3444cf8970a9e41a706fab93e7a6c4:6d9b0b4b9994e8a6afbd3dc3ed983cd51c755afb27cd1dc7825ef59c134a39f7")) - + // Invalid accounts XCTAssertNil(Account("std:0:$")) XCTAssertNil(Account("std:$:0")) XCTAssertNil(Account("st:0:0")) } - + func testInitFromChainAndAddress() { // Valid accounts XCTAssertNotNil(Account(chainIdentifier: "std:0", address: "0")) XCTAssertNotNil(Account(chainIdentifier: "chainstd:8c3444cf8970a9e41a706fab93e7a6c4", address: "6d9b0b4b9994e8a6afbd3dc3ed983cd51c755afb27cd1dc7825ef59c134a39f7")) - + // Invalid accounts XCTAssertNil(Account(chainIdentifier: "std:0", address: "")) XCTAssertNil(Account(chainIdentifier: "std", address: "0")) } - + func testInitFromBlockchain() { let chain = Blockchain("std:0")! - + // Valid accounts XCTAssertNotNil(Account(blockchain: chain, address: "0")) XCTAssertNotNil(Account(blockchain: chain, address: "6d9b0b4b9994e8a6afbd3dc3ed983cd51c755afb27cd1dc7825ef59c134a39f7")) - + // Invalid accounts XCTAssertNil(Account(blockchain: chain, address: "")) XCTAssertNil(Account(blockchain: chain, address: "$")) } - + func testBlockchainIdentifier() { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! XCTAssertEqual(account.blockchainIdentifier, "eip155:1") } - + func testBlockchainExtraction() { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let blockchain = account.blockchain XCTAssertEqual(account.namespace, blockchain.namespace) XCTAssertEqual(account.reference, blockchain.reference) } - + func testAbsoluteString() { let accountString = "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" let account = Account(accountString)! XCTAssertEqual(account.absoluteString, accountString) } - + func testCodable() throws { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let encoded = try JSONEncoder().encode(account) diff --git a/Tests/WalletConnectSignTests/ApproveEngineTests.swift b/Tests/WalletConnectSignTests/ApproveEngineTests.swift index b213d4e30..ac6098c34 100644 --- a/Tests/WalletConnectSignTests/ApproveEngineTests.swift +++ b/Tests/WalletConnectSignTests/ApproveEngineTests.swift @@ -6,7 +6,7 @@ import Combine import WalletConnectUtils final class ApproveEngineTests: XCTestCase { - + var engine: ApproveEngine! var metadata: AppMetadata! var networkingInteractor: NetworkingInteractorMock! @@ -14,9 +14,9 @@ final class ApproveEngineTests: XCTestCase { var pairingStorageMock: WCPairingStorageMock! var sessionStorageMock: WCSessionStorageMock! var proposalPayloadsStore: CodableStore! - + var publishers = Set() - + override func setUp() { metadata = AppMetadata.stub() networkingInteractor = NetworkingInteractorMock() @@ -35,7 +35,7 @@ final class ApproveEngineTests: XCTestCase { sessionStore: sessionStorageMock ) } - + override func tearDown() { networkingInteractor = nil metadata = nil @@ -43,7 +43,7 @@ final class ApproveEngineTests: XCTestCase { pairingStorageMock = nil engine = nil } - + func testApproveProposal() async throws { // Client receives a proposal let topicA = String.generateTopic() @@ -54,14 +54,14 @@ final class ApproveEngineTests: XCTestCase { networkingInteractor.wcRequestPublisherSubject.send(payload) try await engine.approveProposal(proposerPubKey: proposal.proposer.publicKey, validating: SessionNamespace.stubDictionary()) - + let topicB = networkingInteractor.subscriptions.last! - + XCTAssertTrue(networkingInteractor.didCallSubscribe) XCTAssert(cryptoMock.hasAgreementSecret(for: topicB), "Responder must store agreement key for topic B") XCTAssertEqual(networkingInteractor.didRespondOnTopic!, topicA, "Responder must respond on topic A") } - + func testReceiveProposal() { let pairing = WCPairing.stub() let topicA = pairing.topic @@ -80,7 +80,7 @@ final class ApproveEngineTests: XCTestCase { XCTAssertNotNil(try! proposalPayloadsStore.get(key: proposal.proposer.publicKey), "Proposer must store proposal payload") XCTAssertTrue(sessionProposed) } - + func testSessionSettle() async throws { let agreementKeys = AgreementKeys.stub() let topicB = String.generateTopic() @@ -91,7 +91,7 @@ final class ApproveEngineTests: XCTestCase { XCTAssert(networkingInteractor.didSubscribe(to: topicB), "Responder must subscribe for topic B") XCTAssertTrue(networkingInteractor.didCallRequest, "Responder must send session settle payload on topic B") } - + func testHandleSessionSettle() { let sessionTopic = String.generateTopic() cryptoMock.setAgreementSecret(AgreementKeys.stub(), topic: sessionTopic) @@ -99,19 +99,19 @@ final class ApproveEngineTests: XCTestCase { engine.onSessionSettle = { _ in didCallBackOnSessionApproved = true } - + engine.settlingProposal = SessionProposal.stub() networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubSettle(topic: sessionTopic)) - + XCTAssertTrue(sessionStorageMock.getSession(forTopic: sessionTopic)!.acknowledged, "Proposer must store acknowledged session on topic B") XCTAssertTrue(networkingInteractor.didRespondSuccess, "Proposer must send acknowledge on settle request") XCTAssertTrue(didCallBackOnSessionApproved, "Proposer's engine must call back with session") } - + func testHandleSessionSettleAcknowledge() { let session = WCSession.stub(isSelfController: true, acknowledged: false) sessionStorageMock.setSession(session) - + let settleResponse = JSONRPCResponse(id: 1, result: AnyCodable(true)) let response = WCResponse( topic: session.topic, @@ -123,7 +123,7 @@ final class ApproveEngineTests: XCTestCase { XCTAssertTrue(sessionStorageMock.getSession(forTopic: session.topic)!.acknowledged, "Responder must acknowledged session") } - + func testHandleSessionSettleError() { let privateKey = AgreementPrivateKey() let session = WCSession.stub(isSelfController: false, selfPrivateKey: privateKey, acknowledged: false) diff --git a/Tests/WalletConnectSignTests/BlockchainTests.swift b/Tests/WalletConnectSignTests/BlockchainTests.swift index 1db01e063..eac3846fe 100644 --- a/Tests/WalletConnectSignTests/BlockchainTests.swift +++ b/Tests/WalletConnectSignTests/BlockchainTests.swift @@ -2,29 +2,29 @@ import XCTest @testable import WalletConnectSign final class BlockchainTests: XCTestCase { - + func testInitFromString() { // Valid chains XCTAssertNotNil(Blockchain("std:0")) XCTAssertNotNil(Blockchain("chainstd:8c3444cf8970a9e41a706fab93e7a6c4")) - + // Invalid chains XCTAssertNil(Blockchain("st:0")) XCTAssertNil(Blockchain("std:$")) XCTAssertNil(Blockchain("chainstdd:0")) } - + func testInitFromNamespaceAndReference() { // Valid chains XCTAssertNotNil(Blockchain(namespace: "std", reference: "0")) XCTAssertNotNil(Blockchain(namespace: "chainstd", reference: "8c3444cf8970a9e41a706fab93e7a6c4")) - + // Invalid chains XCTAssertNil(Blockchain(namespace: "st", reference: "0")) XCTAssertNil(Blockchain(namespace: "std", reference: "")) XCTAssertNil(Blockchain(namespace: "std", reference: "8c3444cf8970a9e41a706fab93e7a6c44")) } - + func testAbsoluteString() { let chainString = "chainstd:8c3444cf8970a9e41a706fab93e7a6c4" let blockchain = Blockchain(chainString)! diff --git a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift index 766990cfe..a4b5e4665 100644 --- a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift +++ b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift @@ -4,20 +4,19 @@ import WalletConnectUtils import WalletConnectKMS @testable import WalletConnectSign - class ControllerSessionStateMachineTests: XCTestCase { var sut: ControllerSessionStateMachine! var networkingInteractor: NetworkingInteractorMock! var storageMock: WCSessionStorageMock! var cryptoMock: KeyManagementServiceMock! - + override func setUp() { networkingInteractor = NetworkingInteractorMock() storageMock = WCSessionStorageMock() cryptoMock = KeyManagementServiceMock() sut = ControllerSessionStateMachine(networkingInteractor: networkingInteractor, kms: cryptoMock, sessionStore: storageMock, logger: ConsoleLoggerMock()) } - + override func tearDown() { networkingInteractor = nil storageMock = nil @@ -26,7 +25,7 @@ class ControllerSessionStateMachineTests: XCTestCase { } // MARK: - Update Methods - + // FIXME: Implement new namespace tests // func testUpdateNamespacesSuccess() throws { // let session = WCSession.stub(isSelfController: true) @@ -37,13 +36,13 @@ class ControllerSessionStateMachineTests: XCTestCase { // XCTAssertTrue(networkingInteractor.didCallRequest) // XCTAssertEqual(namespacesToUpdate, updatedSession?.namespaces) // } - + func testUpdateNamespacesErrorSessionNotFound() async { await XCTAssertThrowsErrorAsync( try await sut.update(topic: "", namespaces: SessionNamespace.stubDictionary())) { error in XCTAssertTrue(error.isNoSessionMatchingTopicError) } } - + func testUpdateNamespacesErrorSessionNotAcknowledged() async { let session = WCSession.stub(acknowledged: false) storageMock.setSession(session) @@ -67,19 +66,19 @@ class ControllerSessionStateMachineTests: XCTestCase { XCTAssertTrue(error.isUnauthorizedNonControllerCallError) } } - + // MARK: - Update Expiry - + func testUpdateExpirySuccess() async { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: true, expiryDate: tomorrow) storageMock.setSession(session) let twoDays = 2*Time.day await XCTAssertNoThrowAsync(try await sut.extend(topic: session.topic, by: Int64(twoDays))) - let extendedSession = storageMock.getAll().first{$0.topic == session.topic}! + let extendedSession = storageMock.getAll().first {$0.topic == session.topic}! XCTAssertEqual(extendedSession.expiryDate.timeIntervalSinceReferenceDate, TimeTraveler.dateByAdding(days: 2).timeIntervalSinceReferenceDate, accuracy: 1) } - + func testUpdateExpirySessionNotSettled() async { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: false, expiryDate: tomorrow, acknowledged: false) @@ -87,7 +86,7 @@ class ControllerSessionStateMachineTests: XCTestCase { let twoDays = 2*Time.day await XCTAssertThrowsErrorAsync(try await sut.extend(topic: session.topic, by: Int64(twoDays))) } - + func testUpdateExpiryOnNonControllerClient() async { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: false, expiryDate: tomorrow) @@ -95,7 +94,7 @@ class ControllerSessionStateMachineTests: XCTestCase { let twoDays = 2*Time.day await XCTAssertThrowsErrorAsync( try await sut.extend(topic: session.topic, by: Int64(twoDays))) } - + func testUpdateExpiryTtlTooHigh() async { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: true, expiryDate: tomorrow) @@ -103,7 +102,7 @@ class ControllerSessionStateMachineTests: XCTestCase { let tenDays = 10*Time.day await XCTAssertThrowsErrorAsync( try await sut.extend(topic: session.topic, by: Int64(tenDays))) } - + func testUpdateExpiryTtlTooLow() async { let dayAfterTommorow = TimeTraveler.dateByAdding(days: 2) let session = WCSession.stub(isSelfController: true, expiryDate: dayAfterTommorow) diff --git a/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift b/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift index b1354ce58..378a2abe9 100644 --- a/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift +++ b/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift @@ -2,33 +2,33 @@ import Foundation @testable import WalletConnectSign extension NSError { - + static func mock(code: Int = -9999) -> NSError { NSError(domain: "com.walletconnect.sdk.tests.error", code: code, userInfo: nil) } } extension Error { - + var wcError: WalletConnectError? { self as? WalletConnectError } - + var isNoSessionMatchingTopicError: Bool { guard case .noSessionMatchingTopic = wcError else { return false } return true } - + var isSessionNotAcknowledgedError: Bool { guard case .sessionNotAcknowledged = wcError else { return false } return true } - + var isInvalidMethodError: Bool { guard case .invalidMethod = wcError else { return false } return true } - + var isUnauthorizedNonControllerCallError: Bool { guard case .unauthorizedNonControllerCall = wcError else { return false } return true diff --git a/Tests/WalletConnectSignTests/Helpers/TimeTraveler.swift b/Tests/WalletConnectSignTests/Helpers/TimeTraveler.swift index 46aa76b09..1b66229ae 100644 --- a/Tests/WalletConnectSignTests/Helpers/TimeTraveler.swift +++ b/Tests/WalletConnectSignTests/Helpers/TimeTraveler.swift @@ -1,17 +1,17 @@ import Foundation final class TimeTraveler { - + private(set) var referenceDate = Date() - + func generateDate() -> Date { return referenceDate } - + func travel(by timeInterval: TimeInterval) { referenceDate = referenceDate.addingTimeInterval(timeInterval) } - + static func dateByAdding(days: Int) -> Date { Calendar.current.date(byAdding: .day, value: days, to: Date())! } diff --git a/Tests/WalletConnectSignTests/JsonRpcHistoryTests.swift b/Tests/WalletConnectSignTests/JsonRpcHistoryTests.swift index a467501f5..01f4ed5fc 100644 --- a/Tests/WalletConnectSignTests/JsonRpcHistoryTests.swift +++ b/Tests/WalletConnectSignTests/JsonRpcHistoryTests.swift @@ -1,4 +1,3 @@ - import Foundation import XCTest import TestingUtils @@ -6,31 +5,31 @@ import WalletConnectUtils @testable import WalletConnectSign final class JsonRpcHistoryTests: XCTestCase { - + var sut: WalletConnectSign.JsonRpcHistory! - + override func setUp() { sut = JsonRpcHistory(logger: ConsoleLoggerMock(), keyValueStore: CodableStore(defaults: RuntimeKeyValueStorage(), identifier: "")) } - + override func tearDown() { sut = nil } - + func testSetRecord() { let recordinput = getTestJsonRpcRecordInput() XCTAssertFalse(sut.exist(id: recordinput.request.id)) try! sut.set(topic: recordinput.topic, request: recordinput.request) XCTAssertTrue(sut.exist(id: recordinput.request.id)) } - + func testGetRecord() { let recordinput = getTestJsonRpcRecordInput() XCTAssertNil(sut.get(id: recordinput.request.id)) try! sut.set(topic: recordinput.topic, request: recordinput.request) XCTAssertNotNil(sut.get(id: recordinput.request.id)) } - + func testResolve() { let recordinput = getTestJsonRpcRecordInput() try! sut.set(topic: recordinput.topic, request: recordinput.request) @@ -40,7 +39,7 @@ final class JsonRpcHistoryTests: XCTestCase { _ = try! sut.resolve(response: response) XCTAssertNotNil(sut.get(id: jsonRpcResponse.id)?.response) } - + func testThrowsOnResolveDuplicate() { let recordinput = getTestJsonRpcRecordInput() try! sut.set(topic: recordinput.topic, request: recordinput.request) @@ -49,13 +48,13 @@ final class JsonRpcHistoryTests: XCTestCase { _ = try! sut.resolve(response: response) XCTAssertThrowsError(try sut.resolve(response: response)) } - + func testThrowsOnSetDuplicate() { let recordinput = getTestJsonRpcRecordInput() try! sut.set(topic: recordinput.topic, request: recordinput.request) XCTAssertThrowsError(try sut.set(topic: recordinput.topic, request: recordinput.request)) } - + func testDelete() { let recordinput = getTestJsonRpcRecordInput() try! sut.set(topic: recordinput.topic, request: recordinput.request) @@ -63,7 +62,7 @@ final class JsonRpcHistoryTests: XCTestCase { sut.delete(topic: testTopic) XCTAssertNil(sut.get(id: recordinput.request.id)) } - + func testGetPending() { let recordinput1 = getTestJsonRpcRecordInput(id: 1) let recordinput2 = getTestJsonRpcRecordInput(id: 2) diff --git a/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift b/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift index 3943d710a..f2045b917 100644 --- a/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift +++ b/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift @@ -1,4 +1,3 @@ - import Foundation import Combine import WalletConnectUtils @@ -9,11 +8,11 @@ class NetworkingInteractorMock: NetworkInteracting { private(set) var subscriptions: [String] = [] private(set) var unsubscriptions: [String] = [] - + let transportConnectionPublisherSubject = PassthroughSubject() let responsePublisherSubject = PassthroughSubject() let wcRequestPublisherSubject = PassthroughSubject() - + var transportConnectionPublisher: AnyPublisher { transportConnectionPublisherSubject.eraseToAnyPublisher() } @@ -23,80 +22,80 @@ class NetworkingInteractorMock: NetworkInteracting { var responsePublisher: AnyPublisher { responsePublisherSubject.eraseToAnyPublisher() } - + var didCallSubscribe = false - var didRespondOnTopic: String? = nil + var didRespondOnTopic: String? var didCallUnsubscribe = false var didRespondSuccess = false var didRespondError = false var lastErrorCode = -1 - var error: Error? = nil - + var error: Error? + private(set) var requestCallCount = 0 var didCallRequest: Bool { requestCallCount > 0 } - + private(set) var requests: [(topic: String, request: WCRequest)] = [] - + func request(topic: String, payload: WCRequest) async throws { requestCallCount += 1 requests.append((topic, payload)) } - - func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> ())) { + + func requestNetworkAck(_ wcMethod: WCMethod, onTopic topic: String, completion: @escaping ((Error?) -> Void)) { requestCallCount += 1 requests.append((topic, wcMethod.asRequest())) completion(nil) } - - func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>) -> ())?) { + + func requestPeerResponse(_ wcMethod: WCMethod, onTopic topic: String, completion: ((Result, JSONRPCErrorResponse>) -> Void)?) { requestCallCount += 1 requests.append((topic, wcMethod.asRequest())) } - - func respond(topic: String, response: JsonRpcResult, completion: @escaping ((Error?) -> ())) { + + func respond(topic: String, response: JsonRpcResult, completion: @escaping ((Error?) -> Void)) { didRespondOnTopic = topic completion(error) } - + func respond(topic: String, response: JsonRpcResult) async throws { didRespondOnTopic = topic } - + func respondSuccess(payload: WCRequestSubscriptionPayload) async throws { respondSuccess(for: payload) } - + func respondError(payload: WCRequestSubscriptionPayload, reason: ReasonCode) async throws { lastErrorCode = reason.code didRespondError = true } - + func respondSuccess(for payload: WCRequestSubscriptionPayload) { didRespondSuccess = true } - + func subscribe(topic: String) { didCallSubscribe = true subscriptions.append(topic) } - + func unsubscribe(topic: String) { unsubscriptions.append(topic) didCallUnsubscribe = true } - + func sendSubscriptionPayloadOn(topic: String) { let payload = WCRequestSubscriptionPayload(topic: topic, wcRequest: pingRequest) wcRequestPublisherSubject.send(payload) } - + func didSubscribe(to topic: String) -> Bool { subscriptions.contains { $0 == topic } } - + func didUnsubscribe(to topic: String) -> Bool { unsubscriptions.contains { $0 == topic } } } -fileprivate let pingRequest = WCRequest(id: 1, jsonrpc: "2.0", method: .pairingPing, params: WCRequest.Params.pairingPing(PairingType.PingParams())) +private let pingRequest = WCRequest(id: 1, jsonrpc: "2.0", method: .pairingPing, params: WCRequest.Params.pairingPing(PairingType.PingParams())) diff --git a/Tests/WalletConnectSignTests/Mocks/MockedRelayClient.swift b/Tests/WalletConnectSignTests/Mocks/MockedRelayClient.swift index 95122984d..b0f43952f 100644 --- a/Tests/WalletConnectSignTests/Mocks/MockedRelayClient.swift +++ b/Tests/WalletConnectSignTests/Mocks/MockedRelayClient.swift @@ -5,35 +5,35 @@ import Foundation class MockedRelayClient: NetworkRelaying { func subscribe(topic: String) async throws {} - + var socketConnectionStatusPublisherSubject = PassthroughSubject() var socketConnectionStatusPublisher: AnyPublisher { socketConnectionStatusPublisherSubject.eraseToAnyPublisher() } - + func publish(topic: String, payload: String, prompt: Bool) async throws { self.prompt = prompt } - - var onMessage: ((String, String) -> ())? + + var onMessage: ((String, String) -> Void)? var error: Error? var prompt = false - func publish(topic: String, payload: String, prompt: Bool, onNetworkAcknowledge: @escaping ((Error?) -> ())) -> Int64 { + func publish(topic: String, payload: String, prompt: Bool, onNetworkAcknowledge: @escaping ((Error?) -> Void)) -> Int64 { self.prompt = prompt onNetworkAcknowledge(error) return 0 } - - func subscribe(topic: String, completion: @escaping (Error?) -> ()) { + + func subscribe(topic: String, completion: @escaping (Error?) -> Void) { } - - func unsubscribe(topic: String, completion: @escaping ((Error?) -> ())) -> Int64? { + + func unsubscribe(topic: String, completion: @escaping ((Error?) -> Void)) -> Int64? { return 0 } func connect() { } - + func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) { } - + } diff --git a/Tests/WalletConnectSignTests/Mocks/SerializerMock.swift b/Tests/WalletConnectSignTests/Mocks/SerializerMock.swift index de95cc5fa..b7904cc46 100644 --- a/Tests/WalletConnectSignTests/Mocks/SerializerMock.swift +++ b/Tests/WalletConnectSignTests/Mocks/SerializerMock.swift @@ -5,11 +5,10 @@ import WalletConnectUtils @testable import WalletConnectKMS @testable import WalletConnectSign - class SerializerMock: Serializing { var deserialized: Any! var serialized: String = "" - + func serialize(topic: String, encodable: Encodable) throws -> String { try serialize(json: try encodable.json(), agreementKeys: AgreementKeys.stub()) } @@ -19,15 +18,15 @@ class SerializerMock: Serializing { func deserializeJsonRpc(topic: String, message: String) throws -> Result, JSONRPCErrorResponse> { .success(try deserialize(message: message, symmetricKey: Data())) } - - func deserialize(message: String, symmetricKey: Data) throws -> T where T : Codable { + + func deserialize(message: String, symmetricKey: Data) throws -> T where T: Codable { if let deserializedModel = deserialized as? T { return deserializedModel } else { throw NSError.mock() } } - + func serialize(json: String, agreementKeys: AgreementKeys) throws -> String { return serialized } diff --git a/Tests/WalletConnectSignTests/Mocks/WCPairingStorageMock.swift b/Tests/WalletConnectSignTests/Mocks/WCPairingStorageMock.swift index 9961946a8..62b8b34c5 100644 --- a/Tests/WalletConnectSignTests/Mocks/WCPairingStorageMock.swift +++ b/Tests/WalletConnectSignTests/Mocks/WCPairingStorageMock.swift @@ -3,29 +3,29 @@ final class WCPairingStorageMock: WCPairingStorage { var onPairingExpiration: ((WCPairing) -> Void)? - + private(set) var pairings: [String: WCPairing] = [:] - + func hasPairing(forTopic topic: String) -> Bool { pairings[topic] != nil } - + func setPairing(_ pairing: WCPairing) { pairings[pairing.topic] = pairing } - + func getPairing(forTopic topic: String) -> WCPairing? { pairings[topic] } - + func getAll() -> [WCPairing] { Array(pairings.values) } - + func delete(topic: String) { pairings[topic] = nil } - + func deleteAll() { pairings = [:] } diff --git a/Tests/WalletConnectSignTests/Mocks/WCSessionStorageMock.swift b/Tests/WalletConnectSignTests/Mocks/WCSessionStorageMock.swift index c543ecfea..d36ab9cf4 100644 --- a/Tests/WalletConnectSignTests/Mocks/WCSessionStorageMock.swift +++ b/Tests/WalletConnectSignTests/Mocks/WCSessionStorageMock.swift @@ -3,31 +3,30 @@ import Foundation final class WCSessionStorageMock: WCSessionStorage { var onSessionExpiration: ((WCSession) -> Void)? - + private(set) var sessions: [String: WCSession] = [:] - + func hasSession(forTopic topic: String) -> Bool { sessions[topic] != nil } - + func setSession(_ session: WCSession) { sessions[session.topic] = session } - + func getSession(forTopic topic: String) -> WCSession? { return sessions[topic] } - + func getAll() -> [WCSession] { Array(sessions.values) } - + func delete(topic: String) { sessions[topic] = nil } - + func deleteAll() { sessions = [:] } } - diff --git a/Tests/WalletConnectSignTests/NamespaceValidationTests.swift b/Tests/WalletConnectSignTests/NamespaceValidationTests.swift index 5821863c3..599b40c70 100644 --- a/Tests/WalletConnectSignTests/NamespaceValidationTests.swift +++ b/Tests/WalletConnectSignTests/NamespaceValidationTests.swift @@ -2,17 +2,17 @@ import XCTest @testable import WalletConnectSign final class NamespaceValidationTests: XCTestCase { - + let ethChain = Blockchain("eip155:1")! let polyChain = Blockchain("eip155:137")! let cosmosChain = Blockchain("cosmos:cosmoshub-4")! - + let ethAccount = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let polyAccount = Account("eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let cosmosAccount = Account("cosmos:cosmoshub-4:cosmos1t2uflqwqe0fsj0shcfkrvpukewcw40yjj6hdc0")! // MARK: - Proposal namespace validation - + func testValidProposalNamespace() { let namespace = [ "eip155": ProposalNamespace( @@ -32,7 +32,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testChainsMustNotNotBeEmpty() { let namespace = [ "eip155": ProposalNamespace( @@ -43,7 +43,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + func testChainAllowsEmptyMethods() { let namespace = [ "eip155": ProposalNamespace( @@ -54,7 +54,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testChainAllowsEmptyEvents() { let namespace = [ "eip155": ProposalNamespace( @@ -65,7 +65,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testAllChainsContainsNamespacePrefix() { let validNamespace = [ "eip155": ProposalNamespace( @@ -84,7 +84,7 @@ final class NamespaceValidationTests: XCTestCase { XCTAssertNoThrow(try Namespace.validate(validNamespace)) XCTAssertThrowsError(try Namespace.validate(invalidNamespace)) } - + func testExtensionChainsMustNotBeEmpty() { let namespace = [ "eip155": ProposalNamespace( @@ -98,7 +98,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + func testValidateAllProposalNamespaces() { let namespace = [ "eip155": ProposalNamespace( @@ -111,9 +111,9 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + // MARK: - Session namespace validation - + func testValidSessionNamespace() { let namespace = [ "eip155": SessionNamespace( @@ -127,7 +127,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testAccountsMustNotNotBeEmpty() { let namespace = [ "eip155": SessionNamespace( @@ -138,7 +138,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + func testAccountAllowsEmptyMethods() { let namespace = [ "eip155": SessionNamespace( @@ -149,7 +149,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testAccountAllowsEmptyEvents() { let namespace = [ "eip155": SessionNamespace( @@ -160,7 +160,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validate(namespace)) } - + func testAllAccountsContainsNamespacePrefix() { let validNamespace = [ "eip155": SessionNamespace( @@ -179,7 +179,7 @@ final class NamespaceValidationTests: XCTestCase { XCTAssertNoThrow(try Namespace.validate(validNamespace)) XCTAssertThrowsError(try Namespace.validate(invalidNamespace)) } - + func testExtensionAccountsMustNotBeEmpty() { let namespace = [ "eip155": SessionNamespace( @@ -193,7 +193,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + func testValidateAllSessionNamespaces() { let namespace = [ "eip155": SessionNamespace( @@ -206,9 +206,9 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validate(namespace)) } - + // MARK: - Approval namespace validation - + func testNamespaceMustApproveAllMethods() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -234,7 +234,7 @@ final class NamespaceValidationTests: XCTestCase { XCTAssertNoThrow(try Namespace.validateApproved(validSessionNamespace, against: proposalNamespace)) XCTAssertThrowsError(try Namespace.validateApproved(invalidSessionNamespace, against: proposalNamespace)) } - + func testApprovalMustHaveAtLeastOneAccountPerProposedChain() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -260,7 +260,7 @@ final class NamespaceValidationTests: XCTestCase { XCTAssertNoThrow(try Namespace.validateApproved(validSessionNamespace, against: proposalNamespace)) XCTAssertThrowsError(try Namespace.validateApproved(invalidSessionNamespace, against: proposalNamespace)) } - + func testApprovalMayContainMultipleAccountsForSingleChain() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -282,7 +282,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMayExtendProposedMethodsAndEvents() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -300,7 +300,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMayContainNonProposedChainAccounts() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -318,7 +318,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMustContainAllProposedNamespaces() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -354,7 +354,7 @@ final class NamespaceValidationTests: XCTestCase { XCTAssertNoThrow(try Namespace.validateApproved(validNamespace, against: proposalNamespace)) XCTAssertThrowsError(try Namespace.validateApproved(invalidNamespace, against: proposalNamespace)) } - + func testExtensionsMayBeMerged() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -375,7 +375,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMustContainAllEvents() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -393,7 +393,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertThrowsError(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMayExtendoMethodsAndEventsInExtensions() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -421,7 +421,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalExtensionsMayContainAccountsNotDefinedInProposal() { let proposalNamespace = [ "eip155": ProposalNamespace( @@ -449,7 +449,7 @@ final class NamespaceValidationTests: XCTestCase { ] XCTAssertNoThrow(try Namespace.validateApproved(sessionNamespace, against: proposalNamespace)) } - + func testApprovalMayAddExtensionsNotDefinedInProposal() { let proposalNamespace = [ "eip155": ProposalNamespace( diff --git a/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift b/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift index 99b1027ba..5e254eb4c 100644 --- a/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift +++ b/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift @@ -4,29 +4,28 @@ import WalletConnectUtils import WalletConnectKMS @testable import WalletConnectSign - class NonControllerSessionStateMachineTests: XCTestCase { var sut: NonControllerSessionStateMachine! var networkingInteractor: NetworkingInteractorMock! var storageMock: WCSessionStorageMock! var cryptoMock: KeyManagementServiceMock! - + override func setUp() { networkingInteractor = NetworkingInteractorMock() storageMock = WCSessionStorageMock() cryptoMock = KeyManagementServiceMock() sut = NonControllerSessionStateMachine(networkingInteractor: networkingInteractor, kms: cryptoMock, sessionStore: storageMock, logger: ConsoleLoggerMock()) } - + override func tearDown() { networkingInteractor = nil storageMock = nil cryptoMock = nil sut = nil } - + // MARK: - Update Methods - + func testUpdateMethodsPeerSuccess() { var didCallbackUpdatMethods = false let session = WCSession.stub(isSelfController: false) @@ -39,13 +38,13 @@ class NonControllerSessionStateMachineTests: XCTestCase { XCTAssertTrue(didCallbackUpdatMethods) XCTAssertTrue(networkingInteractor.didRespondSuccess) } - + // func testUpdateMethodsPeerErrorInvalidType() { // let session = WCSession.stub(isSelfController: false) // storageMock.setSession(session) // networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubUpdateNamespaces(topic: session.topic, namespaces: [ // Namespace(chains: [Blockchain("eip155:11")!], methods: ["", "m2"], events: ["e1", "e2"])] -//)) +// )) // XCTAssertEqual(networkingInteractor.lastErrorCode, 1004) // } @@ -64,36 +63,34 @@ class NonControllerSessionStateMachineTests: XCTestCase { XCTAssertFalse(networkingInteractor.didRespondSuccess) XCTAssertEqual(networkingInteractor.lastErrorCode, 3004) } - - //MARK: - Update Expiry - + + // MARK: - Update Expiry + func testPeerUpdateExpirySuccess() { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: false, expiryDate: tomorrow) storageMock.setSession(session) let twoDaysFromNowTimestamp = Int64(TimeTraveler.dateByAdding(days: 2).timeIntervalSince1970) - + networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubUpdateExpiry(topic: session.topic, expiry: twoDaysFromNowTimestamp)) - let extendedSession = storageMock.getAll().first{$0.topic == session.topic}! + let extendedSession = storageMock.getAll().first {$0.topic == session.topic}! print(extendedSession.expiryDate) - + XCTAssertEqual(extendedSession.expiryDate.timeIntervalSince1970, TimeTraveler.dateByAdding(days: 2).timeIntervalSince1970, accuracy: 1) } - + func testPeerUpdateExpiryUnauthorized() { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: true, expiryDate: tomorrow) storageMock.setSession(session) let twoDaysFromNowTimestamp = Int64(TimeTraveler.dateByAdding(days: 2).timeIntervalSince1970) - networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubUpdateExpiry(topic: session.topic, expiry: twoDaysFromNowTimestamp)) - - let potentiallyExtendedSession = storageMock.getAll().first{$0.topic == session.topic}! + let potentiallyExtendedSession = storageMock.getAll().first {$0.topic == session.topic}! XCTAssertEqual(potentiallyExtendedSession.expiryDate.timeIntervalSinceReferenceDate, tomorrow.timeIntervalSinceReferenceDate, accuracy: 1, "expiry date has been extended for peer non controller request ") } - + func testPeerUpdateExpiryTtlTooHigh() { let tomorrow = TimeTraveler.dateByAdding(days: 1) let session = WCSession.stub(isSelfController: false, expiryDate: tomorrow) @@ -101,7 +98,7 @@ class NonControllerSessionStateMachineTests: XCTestCase { let tenDaysFromNowTimestamp = Int64(TimeTraveler.dateByAdding(days: 10).timeIntervalSince1970) networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubUpdateExpiry(topic: session.topic, expiry: tenDaysFromNowTimestamp)) - let potentaillyExtendedSession = storageMock.getAll().first{$0.topic == session.topic}! + let potentaillyExtendedSession = storageMock.getAll().first {$0.topic == session.topic}! XCTAssertEqual(potentaillyExtendedSession.expiryDate.timeIntervalSinceReferenceDate, tomorrow.timeIntervalSinceReferenceDate, accuracy: 1, "expiry date has been extended despite ttl to high") } @@ -112,7 +109,7 @@ class NonControllerSessionStateMachineTests: XCTestCase { let oneDayFromNowTimestamp = Int64(TimeTraveler.dateByAdding(days: 10).timeIntervalSince1970) networkingInteractor.wcRequestPublisherSubject.send(WCRequestSubscriptionPayload.stubUpdateExpiry(topic: session.topic, expiry: oneDayFromNowTimestamp)) - let potentaillyExtendedSession = storageMock.getAll().first{$0.topic == session.topic}! + let potentaillyExtendedSession = storageMock.getAll().first {$0.topic == session.topic}! XCTAssertEqual(potentaillyExtendedSession.expiryDate.timeIntervalSinceReferenceDate, tomorrow.timeIntervalSinceReferenceDate, accuracy: 1, "expiry date has been extended despite ttl to low") } } diff --git a/Tests/WalletConnectSignTests/PairEngineTests.swift b/Tests/WalletConnectSignTests/PairEngineTests.swift index b81337ecb..9b581672d 100644 --- a/Tests/WalletConnectSignTests/PairEngineTests.swift +++ b/Tests/WalletConnectSignTests/PairEngineTests.swift @@ -4,18 +4,17 @@ import XCTest @testable import WalletConnectKMS import WalletConnectUtils - final class PairEngineTests: XCTestCase { - + var engine: PairEngine! - + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCPairingStorageMock! var cryptoMock: KeyManagementServiceMock! var proposalPayloadsStore: CodableStore! - + var topicGenerator: TopicGenerator! - + override func setUp() { networkingInteractor = NetworkingInteractorMock() storageMock = WCPairingStorageMock() @@ -24,21 +23,21 @@ final class PairEngineTests: XCTestCase { proposalPayloadsStore = CodableStore(defaults: RuntimeKeyValueStorage(), identifier: "") setupEngine() } - + override func tearDown() { networkingInteractor = nil storageMock = nil cryptoMock = nil engine = nil } - + func setupEngine() { engine = PairEngine( networkingInteractor: networkingInteractor, kms: cryptoMock, pairingStore: storageMock) } - + func testPairMultipleTimesOnSameURIThrows() async { let uri = WalletConnectURI.stub() for i in 1...10 { @@ -49,8 +48,7 @@ final class PairEngineTests: XCTestCase { } } } - - + func testPair() async { let uri = WalletConnectURI.stub() let topic = uri.topic diff --git a/Tests/WalletConnectSignTests/PairingEngineTests.swift b/Tests/WalletConnectSignTests/PairingEngineTests.swift index ce764b6da..4761d37c3 100644 --- a/Tests/WalletConnectSignTests/PairingEngineTests.swift +++ b/Tests/WalletConnectSignTests/PairingEngineTests.swift @@ -9,19 +9,18 @@ func deriveTopic(publicKey: String, privateKey: AgreementPrivateKey) -> String { try! KeyManagementService.generateAgreementKey(from: privateKey, peerPublicKey: publicKey).derivedTopic() } - final class PairingEngineTests: XCTestCase { - + var engine: PairingEngine! var approveEngine: ApproveEngine! - + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCPairingStorageMock! var cryptoMock: KeyManagementServiceMock! - + var topicGenerator: TopicGenerator! var publishers = Set() - + override func setUp() { networkingInteractor = NetworkingInteractorMock() storageMock = WCPairingStorageMock() @@ -29,7 +28,7 @@ final class PairingEngineTests: XCTestCase { topicGenerator = TopicGenerator() setupEngines() } - + override func tearDown() { networkingInteractor = nil storageMock = nil @@ -38,7 +37,7 @@ final class PairingEngineTests: XCTestCase { engine = nil approveEngine = nil } - + func setupEngines() { let meta = AppMetadata.stub() let logger = ConsoleLoggerMock() @@ -61,7 +60,7 @@ final class PairingEngineTests: XCTestCase { sessionStore: WCSessionStorageMock() ) } - + func testCreate() async { let uri = try! await engine.create() XCTAssert(cryptoMock.hasSymmetricKey(for: uri.topic), "Proposer must store the symmetric key matching the URI.") @@ -69,15 +68,15 @@ final class PairingEngineTests: XCTestCase { XCTAssert(networkingInteractor.didSubscribe(to: uri.topic), "Proposer must subscribe to pairing topic.") XCTAssert(storageMock.getPairing(forTopic: uri.topic)?.active == false, "Recently created pairing must be inactive.") } - + func testPropose() async { let pairing = Pairing.stub() let topicA = pairing.topic let relayOptions = RelayProtocolOptions(protocol: "", data: nil) - + // FIXME: namespace stub try! await engine.propose(pairingTopic: pairing.topic, namespaces: ProposalNamespace.stubDictionary(), relay: relayOptions) - + guard let publishTopic = networkingInteractor.requests.first?.topic, let proposal = networkingInteractor.requests.first?.request.sessionProposal else { XCTFail("Proposer must publish a proposal request."); return @@ -85,27 +84,27 @@ final class PairingEngineTests: XCTestCase { XCTAssert(cryptoMock.hasPrivateKey(for: proposal.proposer.publicKey), "Proposer must store the private key matching the public key sent through the proposal.") XCTAssertEqual(publishTopic, topicA) } - + @MainActor func testHandleSessionProposeResponse() async { let uri = try! await engine.create() let pairing = storageMock.getPairing(forTopic: uri.topic)! let topicA = pairing.topic let relayOptions = RelayProtocolOptions(protocol: "", data: nil) - + // Client proposes session // FIXME: namespace stub try! await engine.propose(pairingTopic: pairing.topic, namespaces: ProposalNamespace.stubDictionary(), relay: relayOptions) - + guard let request = networkingInteractor.requests.first?.request, let proposal = networkingInteractor.requests.first?.request.sessionProposal else { XCTFail("Proposer must publish session proposal request"); return } - + // Client receives proposal response response let responder = Participant.stub() let proposalResponse = SessionType.ProposeResponse(relay: relayOptions, responderPublicKey: responder.publicKey) - + let jsonRpcResponse = JSONRPCResponse(id: request.id, result: AnyCodable.decoded(proposalResponse)) let response = WCResponse(topic: topicA, chainId: nil, @@ -123,53 +122,53 @@ final class PairingEngineTests: XCTestCase { XCTAssert(storedPairing.active) XCTAssertEqual(topicB, sessionTopic, "Responder engine calls back with session topic") } - + func testSessionProposeError() async { let uri = try! await engine.create() let pairing = storageMock.getPairing(forTopic: uri.topic)! let topicA = pairing.topic let relayOptions = RelayProtocolOptions(protocol: "", data: nil) - + // Client propose session // FIXME: namespace stub try! await engine.propose(pairingTopic: pairing.topic, namespaces: ProposalNamespace.stubDictionary(), relay: relayOptions) - + guard let request = networkingInteractor.requests.first?.request, let proposal = networkingInteractor.requests.first?.request.sessionProposal else { XCTFail("Proposer must publish session proposal request"); return } - + let response = WCResponse.stubError(forRequest: request, topic: topicA) networkingInteractor.responsePublisherSubject.send(response) - + XCTAssert(networkingInteractor.didUnsubscribe(to: pairing.topic), "Proposer must unsubscribe if pairing is inactive.") XCTAssertFalse(storageMock.hasPairing(forTopic: pairing.topic), "Proposer must delete an inactive pairing.") XCTAssertFalse(cryptoMock.hasSymmetricKey(for: pairing.topic), "Proposer must delete symmetric key if pairing is inactive.") XCTAssertFalse(cryptoMock.hasPrivateKey(for: proposal.proposer.publicKey), "Proposer must remove private key for rejected session") } - + func testSessionProposeErrorOnActivePairing() async { let uri = try! await engine.create() let pairing = storageMock.getPairing(forTopic: uri.topic)! let topicA = pairing.topic let relayOptions = RelayProtocolOptions(protocol: "", data: nil) - + // Client propose session // FIXME: namespace stub try? await engine.propose(pairingTopic: pairing.topic, namespaces: ProposalNamespace.stubDictionary(), relay: relayOptions) - + guard let request = networkingInteractor.requests.first?.request, let proposal = networkingInteractor.requests.first?.request.sessionProposal else { XCTFail("Proposer must publish session proposal request"); return } - + var storedPairing = storageMock.getPairing(forTopic: topicA)! storedPairing.activate() storageMock.setPairing(storedPairing) - + let response = WCResponse.stubError(forRequest: request, topic: topicA) networkingInteractor.responsePublisherSubject.send(response) - + XCTAssertFalse(networkingInteractor.didUnsubscribe(to: pairing.topic), "Proposer must not unsubscribe if pairing is active.") XCTAssert(storageMock.hasPairing(forTopic: pairing.topic), "Proposer must not delete an active pairing.") XCTAssert(cryptoMock.hasSymmetricKey(for: pairing.topic), "Proposer must not delete symmetric key if pairing is active.") diff --git a/Tests/WalletConnectSignTests/SequenceStoreTests.swift b/Tests/WalletConnectSignTests/SequenceStoreTests.swift index 4a20b1812..4ec7bbd67 100644 --- a/Tests/WalletConnectSignTests/SequenceStoreTests.swift +++ b/Tests/WalletConnectSignTests/SequenceStoreTests.swift @@ -9,15 +9,15 @@ struct ExpirableSequenceStub: ExpirableSequence, Equatable { } final class SequenceStoreTests: XCTestCase { - + var sut: SequenceStore! - + var storageFake: RuntimeKeyValueStorage! - + var timeTraveler: TimeTraveler! - + let defaultTime = TimeInterval(Time.day) - + override func setUp() { timeTraveler = TimeTraveler() sut = makeStore("test") @@ -25,20 +25,20 @@ final class SequenceStoreTests: XCTestCase { XCTFail("Unexpected expiration call") } } - + override func tearDown() { timeTraveler = nil storageFake = nil sut = nil } - + private func makeStore(_ identifier: String) -> SequenceStore { return SequenceStore( store: .init(defaults: RuntimeKeyValueStorage(), identifier: identifier), dateInitializer: timeTraveler.generateDate ) } - + private func stubSequence(expiry: TimeInterval? = nil) -> ExpirableSequenceStub { ExpirableSequenceStub( topic: String.generateTopic(), @@ -46,9 +46,9 @@ final class SequenceStoreTests: XCTestCase { expiryDate: timeTraveler.referenceDate.addingTimeInterval(expiry ?? defaultTime) ) } - + // MARK: - CRUD Tests - + func testRoundTrip() { let sequence = stubSequence() sut.setSequence(sequence) @@ -56,7 +56,7 @@ final class SequenceStoreTests: XCTestCase { XCTAssertTrue(sut.hasSequence(forTopic: sequence.topic)) XCTAssertEqual(retrieved, sequence) } - + func testGetAll() { let sequenceArray = (1...10).map { _ -> ExpirableSequenceStub in let sequence = stubSequence() @@ -69,7 +69,7 @@ final class SequenceStoreTests: XCTestCase { XCTAssert(retrieved.contains($0)) } } - + func testDelete() { let sequence = stubSequence() sut.setSequence(sequence) @@ -78,14 +78,14 @@ final class SequenceStoreTests: XCTestCase { XCTAssertFalse(sut.hasSequence(forTopic: sequence.topic)) XCTAssertNil(retrieved) } - + func testDeleteAll() { let sequence = stubSequence() sut.setSequence(sequence) - + let sut2 = makeStore("test2") sut2.setSequence(sequence) - + XCTAssertFalse(sut.getAll().isEmpty) XCTAssertFalse(sut2.getAll().isEmpty) @@ -94,34 +94,34 @@ final class SequenceStoreTests: XCTestCase { XCTAssertTrue(sut.getAll().isEmpty) XCTAssertFalse(sut2.getAll().isEmpty) } - + // MARK: - Expiration Tests - + func testHasSequenceExpiration() { let sequence = stubSequence() - var expired: ExpirableSequenceStub? = nil + var expired: ExpirableSequenceStub? sut.onSequenceExpiration = { expired = $0 } - + sut.setSequence(sequence) timeTraveler.travel(by: defaultTime) - + XCTAssertFalse(sut.hasSequence(forTopic: sequence.topic)) XCTAssertEqual(expired?.topic, sequence.topic) } - + func testGetSequenceExpiration() { let sequence = stubSequence() - var expired: ExpirableSequenceStub? = nil + var expired: ExpirableSequenceStub? sut.onSequenceExpiration = { expired = $0 } - + sut.setSequence(sequence) timeTraveler.travel(by: defaultTime) let retrieved = try? sut.getSequence(forTopic: sequence.topic) - + XCTAssertNil(retrieved) XCTAssertEqual(expired?.topic, sequence.topic) } - + func testGetAllExpiration() { let sequenceCount = 10 var expiredCount = 0 @@ -130,14 +130,14 @@ final class SequenceStoreTests: XCTestCase { let sequence = stubSequence() sut.setSequence(sequence) } - + timeTraveler.travel(by: defaultTime) let retrieved = sut.getAll() - + XCTAssert(retrieved.isEmpty) XCTAssert(expiredCount == sequenceCount) } - + func testGetAllPartialExpiration() { var expiredCount = 0 sut.onSequenceExpiration = { _ in expiredCount += 1 } @@ -151,10 +151,10 @@ final class SequenceStoreTests: XCTestCase { let sequence = stubSequence() sut.setSequence(sequence) } - + timeTraveler.travel(by: defaultTime) let retrievedCount = sut.getAll().count - + XCTAssert(retrievedCount == persistentCount) XCTAssert(expiredCount == expirableCount) } diff --git a/Tests/WalletConnectSignTests/Stub/AgreementSecret+Stub.swift b/Tests/WalletConnectSignTests/Stub/AgreementSecret+Stub.swift index 2416bb7a2..aef7cc1be 100644 --- a/Tests/WalletConnectSignTests/Stub/AgreementSecret+Stub.swift +++ b/Tests/WalletConnectSignTests/Stub/AgreementSecret+Stub.swift @@ -2,7 +2,7 @@ import Foundation @testable import WalletConnectKMS extension AgreementKeys { - + static func stub() -> AgreementKeys { let key = try! SymmetricKey(rawRepresentation: Data.randomBytes(count: 32)) return AgreementKeys(sharedKey: key, publicKey: AgreementPrivateKey().publicKey) diff --git a/Tests/WalletConnectSignTests/Stub/Stubs.swift b/Tests/WalletConnectSignTests/Stub/Stubs.swift index de61c3ba7..2cb01a131 100644 --- a/Tests/WalletConnectSignTests/Stub/Stubs.swift +++ b/Tests/WalletConnectSignTests/Stub/Stubs.swift @@ -70,22 +70,22 @@ extension AgreementPeer { } extension WCRequestSubscriptionPayload { - + static func stubUpdateNamespaces(topic: String, namespaces: [String: SessionNamespace] = SessionNamespace.stubDictionary()) -> WCRequestSubscriptionPayload { let updateMethod = WCMethod.wcSessionUpdate(SessionType.UpdateParams(namespaces: namespaces)).asRequest() return WCRequestSubscriptionPayload(topic: topic, wcRequest: updateMethod) } - + static func stubUpdateExpiry(topic: String, expiry: Int64) -> WCRequestSubscriptionPayload { let updateExpiryMethod = WCMethod.wcSessionExtend(SessionType.UpdateExpiryParams(expiry: expiry)).asRequest() return WCRequestSubscriptionPayload(topic: topic, wcRequest: updateExpiryMethod) } - + static func stubSettle(topic: String) -> WCRequestSubscriptionPayload { let method = WCMethod.wcSessionSettle(SessionType.SettleParams.stub()) return WCRequestSubscriptionPayload(topic: topic, wcRequest: method.asRequest()) } - + static func stubRequest(topic: String, method: String, chainId: Blockchain) -> WCRequestSubscriptionPayload { let params = SessionType.RequestParams( request: SessionType.RequestParams.Request(method: method, params: AnyCodable(EmptyCodable())), diff --git a/Tests/WalletConnectSignTests/Stub/WalletConnectURI+Stub.swift b/Tests/WalletConnectSignTests/Stub/WalletConnectURI+Stub.swift index 1ece8084d..5d5129228 100644 --- a/Tests/WalletConnectSignTests/Stub/WalletConnectURI+Stub.swift +++ b/Tests/WalletConnectSignTests/Stub/WalletConnectURI+Stub.swift @@ -3,7 +3,7 @@ import CryptoKit extension WalletConnectURI { - + static func stub(isController: Bool = false) -> WalletConnectURI { WalletConnectURI( topic: String.generateTopic(), diff --git a/Tests/WalletConnectSignTests/WCPairingTests.swift b/Tests/WalletConnectSignTests/WCPairingTests.swift index 04825c62e..951fdb430 100644 --- a/Tests/WalletConnectSignTests/WCPairingTests.swift +++ b/Tests/WalletConnectSignTests/WCPairingTests.swift @@ -2,45 +2,45 @@ import XCTest @testable import WalletConnectSign final class WCPairingTests: XCTestCase { - + var referenceDate: Date! - + override func setUp() { referenceDate = Date() func getDate() -> Date { return referenceDate } WCPairing.dateInitializer = getDate } - + override func tearDown() { WCPairing.dateInitializer = Date.init } - + func testAbsoluteValues() { XCTAssertEqual(WCPairing.timeToLiveInactive, 5 * .minute, "Inactive time-to-live is 5 minutes.") XCTAssertEqual(WCPairing.timeToLiveActive, 30 * .day, "Active time-to-live is 30 days.") } - + func testInitInactiveFromTopic() { let pairing = WCPairing(topic: "") let inactiveExpiry = referenceDate.advanced(by: WCPairing.timeToLiveInactive) XCTAssertFalse(pairing.active) XCTAssertEqual(pairing.expiryDate, inactiveExpiry) } - + func testInitInactiveFromURI() { let pairing = WCPairing(uri: WalletConnectURI.stub()) let inactiveExpiry = referenceDate.advanced(by: WCPairing.timeToLiveInactive) XCTAssertFalse(pairing.active) XCTAssertEqual(pairing.expiryDate, inactiveExpiry) } - + func testUpdateExpiry() { var pairing = WCPairing(topic: "") let activeExpiry = referenceDate.advanced(by: WCPairing.timeToLiveActive) try? pairing.updateExpiry() XCTAssertEqual(pairing.expiryDate, activeExpiry) } - + func testActivate() { var pairing = WCPairing(topic: "") let activeExpiry = referenceDate.advanced(by: WCPairing.timeToLiveActive) diff --git a/Tests/WalletConnectSignTests/WCRelayTests.swift b/Tests/WalletConnectSignTests/WCRelayTests.swift index b0978732d..51baee654 100644 --- a/Tests/WalletConnectSignTests/WCRelayTests.swift +++ b/Tests/WalletConnectSignTests/WCRelayTests.swift @@ -1,4 +1,3 @@ - import Foundation import Combine import XCTest @@ -25,11 +24,11 @@ class NetworkingInteractorTests: XCTestCase { relayClient = nil serializer = nil } - + func testNotifiesOnEncryptedWCJsonRpcRequest() { let requestExpectation = expectation(description: "notifies with request") let topic = "fefc3dc39cacbc562ed58f92b296e2d65a6b07ef08992b93db5b3cb86280635a" - networkingInteractor.wcRequestPublisher.sink { (request) in + networkingInteractor.wcRequestPublisher.sink { (_) in requestExpectation.fulfill() }.store(in: &publishers) serializer.deserialized = request @@ -53,7 +52,7 @@ extension NetworkingInteractorTests { } } -fileprivate let testPayload = +private let testPayload = """ { "id":1630300527198334, @@ -68,5 +67,5 @@ fileprivate let testPayload = } } """ -//TODO - change for different request -fileprivate let request = WCRequest(id: 1, jsonrpc: "2.0", method: .pairingPing, params: WCRequest.Params.pairingPing(PairingType.PingParams())) +// TODO - change for different request +private let request = WCRequest(id: 1, jsonrpc: "2.0", method: .pairingPing, params: WCRequest.Params.pairingPing(PairingType.PingParams())) diff --git a/Tests/WalletConnectSignTests/WCSessionTests.swift b/Tests/WalletConnectSignTests/WCSessionTests.swift index 635f71973..70a08ec32 100644 --- a/Tests/WalletConnectSignTests/WCSessionTests.swift +++ b/Tests/WalletConnectSignTests/WCSessionTests.swift @@ -2,11 +2,11 @@ import XCTest @testable import WalletConnectSign final class WCSessionTests: XCTestCase { - + let ethAccount = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let polyAccount = Account("eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! let cosmosAccount = Account("cosmos:cosmoshub-4:cosmos1t2uflqwqe0fsj0shcfkrvpukewcw40yjj6hdc0")! - + func testHasPermissionForMethod() { let namespace = [ "eip155": SessionNamespace( @@ -19,7 +19,7 @@ final class WCSessionTests: XCTestCase { session.updateNamespaces(namespace) XCTAssertTrue(session.hasPermission(forMethod: "method", onChain: ethAccount.blockchain)) } - + func testHasPermissionForMethodInExtension() { let namespace = [ "eip155": SessionNamespace( @@ -36,7 +36,7 @@ final class WCSessionTests: XCTestCase { session.updateNamespaces(namespace) XCTAssertTrue(session.hasPermission(forMethod: "method", onChain: ethAccount.blockchain)) } - + func testDenyPermissionForMethodInOtherChain() { let namespace = [ "eip155": SessionNamespace( @@ -48,13 +48,13 @@ final class WCSessionTests: XCTestCase { accounts: [cosmosAccount], methods: ["method"], events: [], - extensions: nil), + extensions: nil) ] var session = WCSession.stub() session.updateNamespaces(namespace) XCTAssertFalse(session.hasPermission(forMethod: "method", onChain: ethAccount.blockchain)) } - + func testDenyPermissionForMethodInOtherChainExtension() { let namespace = [ "eip155": SessionNamespace( @@ -71,7 +71,7 @@ final class WCSessionTests: XCTestCase { session.updateNamespaces(namespace) XCTAssertFalse(session.hasPermission(forMethod: "method", onChain: ethAccount.blockchain)) } - + func testHasPermissionForEvent() { let namespace = [ "eip155": SessionNamespace( @@ -84,7 +84,7 @@ final class WCSessionTests: XCTestCase { session.updateNamespaces(namespace) XCTAssertTrue(session.hasPermission(forEvent: "event", onChain: ethAccount.blockchain)) } - + func testHasPermissionForEventInExtension() { let namespace = [ "eip155": SessionNamespace( @@ -101,7 +101,7 @@ final class WCSessionTests: XCTestCase { session.updateNamespaces(namespace) XCTAssertTrue(session.hasPermission(forEvent: "event", onChain: ethAccount.blockchain)) } - + func testDenyPermissionForEventInOtherChain() { let namespace = [ "eip155": SessionNamespace( @@ -113,13 +113,13 @@ final class WCSessionTests: XCTestCase { accounts: [cosmosAccount], methods: [], events: ["event"], - extensions: nil), + extensions: nil) ] var session = WCSession.stub() session.updateNamespaces(namespace) XCTAssertFalse(session.hasPermission(forEvent: "event", onChain: ethAccount.blockchain)) } - + func testDenyPermissionForEventInOtherChainExtension() { let namespace = [ "eip155": SessionNamespace( diff --git a/Tests/WalletConnectSignTests/WalletConnectURITests.swift b/Tests/WalletConnectSignTests/WalletConnectURITests.swift index 492684dc8..22e9d01ca 100644 --- a/Tests/WalletConnectSignTests/WalletConnectURITests.swift +++ b/Tests/WalletConnectSignTests/WalletConnectURITests.swift @@ -1,14 +1,14 @@ import XCTest @testable import WalletConnectSign -fileprivate let stubTopic = "8097df5f14871126866252c1b7479a14aefb980188fc35ec97d130d24bd887c8" -fileprivate let stubSymKey = "587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303" -fileprivate let stubProtocol = "waku" +private let stubTopic = "8097df5f14871126866252c1b7479a14aefb980188fc35ec97d130d24bd887c8" +private let stubSymKey = "587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303" +private let stubProtocol = "waku" -fileprivate let stubURI = "wc:7f6e504bfad60b485450578e05678ed3e8e8c4751d3c6160be17160d63ec90f9@2?symKey=587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303&relay-protocol=waku" +private let stubURI = "wc:7f6e504bfad60b485450578e05678ed3e8e8c4751d3c6160be17160d63ec90f9@2?symKey=587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303&relay-protocol=waku" final class WalletConnectURITests: XCTestCase { - + func testInitURIToString() { let inputURI = WalletConnectURI( topic: "8097df5f14871126866252c1b7479a14aefb980188fc35ec97d130d24bd887c8", @@ -18,14 +18,14 @@ final class WalletConnectURITests: XCTestCase { let outputURI = WalletConnectURI(string: uriString) XCTAssertEqual(inputURI, outputURI) } - + func testInitStringToURI() { let inputURIString = stubURI let uri = WalletConnectURI(string: inputURIString) let outputURIString = uri?.absoluteString XCTAssertEqual(inputURIString, outputURIString) } - + func testInitStringToURIAlternate() { let expectedString = stubURI let inputURIString = expectedString.replacingOccurrences(of: "wc:", with: "wc://") @@ -33,25 +33,25 @@ final class WalletConnectURITests: XCTestCase { let outputURIString = uri?.absoluteString XCTAssertEqual(expectedString, outputURIString) } - + func testInitFailsBadScheme() { let inputURIString = stubURI.replacingOccurrences(of: "wc:", with: "") let uri = WalletConnectURI(string: inputURIString) XCTAssertNil(uri) } - + func testInitFailsMalformedURL() { let inputURIString = "wc://<" let uri = WalletConnectURI(string: inputURIString) XCTAssertNil(uri) } - + func testInitFailsNoSymKeyParam() { let inputURIString = stubURI.replacingOccurrences(of: "symKey=\(stubSymKey)", with: "") let uri = WalletConnectURI(string: inputURIString) XCTAssertNil(uri) } - + func testInitFailsNoRelayParam() { let inputURIString = stubURI.replacingOccurrences(of: "&relay-protocol=\(stubProtocol)", with: "") let uri = WalletConnectURI(string: inputURIString) diff --git a/Tests/WalletConnectSignTests/XCTestManifests.swift b/Tests/WalletConnectSignTests/XCTestManifests.swift index b325fb8a8..fe7de8b65 100644 --- a/Tests/WalletConnectSignTests/XCTestManifests.swift +++ b/Tests/WalletConnectSignTests/XCTestManifests.swift @@ -3,7 +3,7 @@ import XCTest #if !canImport(ObjectiveC) public func allTests() -> [XCTestCaseEntry] { return [ - testCase(WalletConnectTests.allTests), + testCase(WalletConnectTests.allTests) ] } #endif diff --git a/Tests/WalletConnectUtilsTests/String+ExtensionTests.swift b/Tests/WalletConnectUtilsTests/String+ExtensionTests.swift index b882610f7..d783cfa2e 100644 --- a/Tests/WalletConnectUtilsTests/String+ExtensionTests.swift +++ b/Tests/WalletConnectUtilsTests/String+ExtensionTests.swift @@ -2,37 +2,37 @@ import XCTest @testable import WalletConnectUtils final class StringExtensionTests: XCTestCase { - + func testGenericPasswordConvertible() { let string = UUID().uuidString.replacingOccurrences(of: "-", with: "") let restoredString = try? String(rawRepresentation: string.rawRepresentation) XCTAssertEqual(string, restoredString) } - + func testConformanceToCAIP2() { // Minimum and maximum length cases XCTAssertTrue(String.conformsToCAIP2("std:0"), "Dummy min length (3+1+1 = 5 chars/bytes)") XCTAssertTrue(String.conformsToCAIP2("chainstd:8C3444cf8970a9e41a706fab93e7a6c4"), "Dummy max length (8+1+32 = 41 chars/bytes)") - + // Invalid namespace formatting XCTAssertFalse(String.conformsToCAIP2("chainstdd:0"), "Namespace overflow") XCTAssertFalse(String.conformsToCAIP2("st:00"), "Namespace underflow") XCTAssertFalse(String.conformsToCAIP2("chain$td:0"), "Namespace uses special character") XCTAssertFalse(String.conformsToCAIP2("Chainstd:0"), "Namespace uses uppercase letter") XCTAssertFalse(String.conformsToCAIP2(":8c3444cf8970a9e41a706fab93e7a6c4"), "Empty namespace") - + // Invalid reference formatting XCTAssertFalse(String.conformsToCAIP2("chainstd:8c3444cf8970a9e41a706fab93e7a6c44"), "Reference overflow") XCTAssertFalse(String.conformsToCAIP2("chainstd:0!"), "Reference uses special character") XCTAssertFalse(String.conformsToCAIP2("chainstd:"), "Empty reference") - + // Malformed identifier XCTAssertFalse(String.conformsToCAIP2("chainstd8c3444cf8970a9e41a706fab93e7a6c4"), "No colon") XCTAssertFalse(String.conformsToCAIP2("chainstd:8c3444cf8970a9e41a706fab93e7a6c4:"), "Multiple colon in suffix") XCTAssertFalse(String.conformsToCAIP2("chainstd:8c3444cf8970a9e:41a706fab93e7a6c"), "Multiple colons") XCTAssertFalse(String.conformsToCAIP2(""), "Empty string") } - + func testRealExamplesConformanceToCAIP2() { XCTAssertTrue(String.conformsToCAIP2("eip155:1"), "Ethereum mainnet") XCTAssertTrue(String.conformsToCAIP2("bip122:000000000019d6689c085ae165831e93"), "Bitcoin mainnet") @@ -43,17 +43,17 @@ final class StringExtensionTests: XCTestCase { XCTAssertTrue(String.conformsToCAIP2("cosmos:iov-mainnet"), "IOV Mainnet (Tendermint + weave)") XCTAssertTrue(String.conformsToCAIP2("lip9:9ee11e9df416b18b"), "Lisk Mainnet (LIP-0009)") } - + func testConformanceToCAIP10() { // Minimum and maximum length cases XCTAssertTrue(String.conformsToCAIP10("std:0:0"), "Dummy min length (3+1+1+1+1 = 7 chars/bytes)") XCTAssertTrue(String.conformsToCAIP10("chainstd:8c3444cf8970a9e41a706fab93e7a6c4:6d9b0b4b9994e8a6afbd3dc3ed983cd51c755afb27cd1dc7825ef59c134a39f7"), "Dummy max length (64+1+8+1+32 = 106 chars/bytes)") - + // Invalid address formatting XCTAssertFalse(String.conformsToCAIP10("chainstd:0:6d9b0b4b9994e8a6afbd3dc3ed983cd51c755afb27cd1dc7825ef59c134a39f77"), "Address overflow") XCTAssertFalse(String.conformsToCAIP10("chainstd:0:$"), "Address uses special character") XCTAssertFalse(String.conformsToCAIP10("chainstd:0:"), "Empty address") - + // Malformed identifier XCTAssertFalse(String.conformsToCAIP10("st:0:0"), "Bad namespace") XCTAssertFalse(String.conformsToCAIP10("std:#:0"), "Bad reference") @@ -64,7 +64,7 @@ final class StringExtensionTests: XCTestCase { XCTAssertFalse(String.conformsToCAIP10("chainstd:0::0"), "Repeated colons") XCTAssertFalse(String.conformsToCAIP10(""), "Empty string") } - + func testRealExamplesConformanceToCAIP10() { XCTAssertTrue(String.conformsToCAIP10("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"), "Ethereum mainnet") XCTAssertTrue(String.conformsToCAIP10("bip122:000000000019d6689c085ae165831e93:128Lkh3S7CkDTBZ8W7BbpsN3YYizJMp8p6"), "Bitcoin mainnet")