Skip to content

Commit

Permalink
Merge pull request #477 from WalletConnect/#472-extend-pairing
Browse files Browse the repository at this point in the history
[Auth] #472 extend pairing
  • Loading branch information
llbartekll authored Sep 1, 2022
2 parents feb6c60 + 50ed654 commit bc9095a
Show file tree
Hide file tree
Showing 24 changed files with 108 additions and 98 deletions.
1 change: 0 additions & 1 deletion Example/DApp/Auth/AuthView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,3 @@ struct CircleButtonStyle: ButtonStyle {
.cornerRadius(8.0)
}
}

4 changes: 2 additions & 2 deletions Example/DApp/Auth/AuthViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class AuthViewModel: ObservableObject {
}

func walletDidPressed() {

}

func deeplinkPressed() {
Expand All @@ -47,7 +47,7 @@ final class AuthViewModel: ObservableObject {
private extension AuthViewModel {

func setupSubscriptions() {
Auth.instance.authResponsePublisher.sink { [weak self] (id, result) in
Auth.instance.authResponsePublisher.sink { [weak self] (_, result) in
switch result {
case .success(let cacao):
self?.state = .signed(cacao)
Expand Down
2 changes: 1 addition & 1 deletion Example/DApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
private let authCoordinator = AuthCoordinator()

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
Relay.configure(projectId: "8ba9ee138960775e5231b70cc5ef1c3a",socketFactory: SocketFactory())
Relay.configure(projectId: "8ba9ee138960775e5231b70cc5ef1c3a", socketFactory: SocketFactory())

setupWindow(scene: scene)
}
Expand Down
6 changes: 3 additions & 3 deletions Example/IntegrationTests/Auth/AuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ final class AuthTests: XCTestCase {
}
}
.store(in: &publishers)
app.authResponsePublisher.sink { (id, result) in
app.authResponsePublisher.sink { (_, result) in
guard case .success = result else { XCTFail(); return }
responseExpectation.fulfill()
}
Expand All @@ -90,7 +90,7 @@ final class AuthTests: XCTestCase {
}
}
.store(in: &publishers)
app.authResponsePublisher.sink { (id, result) in
app.authResponsePublisher.sink { (_, result) in
guard case .failure(let error) = result else { XCTFail(); return }
XCTAssertEqual(error, .userRejeted)
responseExpectation.fulfill()
Expand All @@ -111,7 +111,7 @@ final class AuthTests: XCTestCase {
}
}
.store(in: &publishers)
app.authResponsePublisher.sink { (id, result) in
app.authResponsePublisher.sink { (_, result) in
guard case .failure(let error) = result else { XCTFail(); return }
XCTAssertEqual(error, .signatureVerificationFailed)
responseExpectation.fulfill()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
MigrationConfigurator(app: app),
ThirdPartyConfigurator(),
ApplicationConfigurator(app: app),
AppearanceConfigurator(),
AppearanceConfigurator()
]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import SwiftUI

struct ScanQR: UIViewRepresentable {

class Coordinator: ScanQRViewDelegate {
private let onValue: (String) -> Void
private let onError: (Error) -> Void

init(onValue: @escaping (String) -> Void, onError: @escaping (Error) -> Void) {
self.onValue = onValue
self.onError = onError
}

func scanDidDetect(value: String) {
onValue(value)
}

func scanDidFail(with error: Error) {
onError(error)
}
}

let onValue: (String) -> Void
let onError: (Error) -> Void

func makeUIView(context: Context) -> ScanQRView {
let view = ScanQRView()
view.delegate = context.coordinator
return view
}

func updateUIView(_ uiView: ScanQRView, context: Context) {

}

func makeCoordinator() -> Coordinator {
return Coordinator(onValue: onValue, onError: onError)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ final class ScanQRView: UIView {
enum Errors: Error {
case deviceNotFound
}

weak var delegate: ScanQRViewDelegate?

private let targetSize = CGSize(
width: UIScreen.main.bounds.width - 32.0,
height: UIScreen.main.bounds.width - 32.0
)

private var videoPreviewLayer: AVCaptureVideoPreviewLayer?
private var captureSession: AVCaptureSession?

private lazy var borderView: UIView = {
let borderView = ScanTargetView(radius: 24.0, color: .white, strokeWidth: 2.0, length: 36.0)
borderView.alpha = 0.85
Expand All @@ -34,21 +34,21 @@ final class ScanQRView: UIView {
bluredView.layer.mask = createMaskLayer()
return bluredView
}()

override init(frame: CGRect) {
super.init(frame: frame)

setupView()
startCaptureSession()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
super.layoutSubviews()

updateFrames()
updateOrientation()
}
Expand All @@ -61,7 +61,7 @@ final class ScanQRView: UIView {
// MARK: AVCaptureMetadataOutputObjectsDelegate

extension ScanQRView: AVCaptureMetadataOutputObjectsDelegate {

func metadataOutput(_ metadataOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard
let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
Expand All @@ -76,14 +76,14 @@ extension ScanQRView: AVCaptureMetadataOutputObjectsDelegate {
// MARK: Privates

private extension ScanQRView {

private func setupView() {
backgroundColor = .black

addSubview(bluredView)
addSubview(borderView)
}

private func createMaskLayer() -> CAShapeLayer {
let maskPath = UIBezierPath(rect: bounds)
let rect = UIBezierPath(
Expand All @@ -98,76 +98,76 @@ private extension ScanQRView {
)
maskPath.append(rect)
maskPath.usesEvenOddFillRule = true

let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
maskLayer.fillRule = .evenOdd
return maskLayer
}

private func startCaptureSession() {
DispatchQueue.global().async { [weak self] in
guard let self = self else { return }

do {
let session = try self.createCaptureSession()
session.startRunning()
self.captureSession = session

DispatchQueue.main.async { self.setupVideoPreviewLayer(with: session) }
} catch {
DispatchQueue.main.async { self.delegate?.scanDidFail(with: error) }
}
}
}

private func createCaptureSession() throws -> AVCaptureSession {
guard let captureDevice = AVCaptureDevice.default(for: .video) else {
throw Errors.deviceNotFound
}

let input = try AVCaptureDeviceInput(device: captureDevice)

let session = AVCaptureSession()
session.addInput(input)

let captureMetadataOutput = AVCaptureMetadataOutput()
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: .main)
session.addOutput(captureMetadataOutput)

captureMetadataOutput.metadataObjectTypes = [.qr]

return session
}

private func stopCaptureSession() {
captureSession?.stopRunning()
captureSession = nil
}

private func setupVideoPreviewLayer(with session: AVCaptureSession) {
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer.frame = layer.bounds
videoPreviewLayer = previewLayer

layer.insertSublayer(previewLayer, at: 0)
}

private func updateFrames() {
borderView.frame.size = targetSize
borderView.center = center
bluredView.frame = bounds
bluredView.layer.mask = createMaskLayer()
videoPreviewLayer?.frame = layer.bounds
}

private func updateOrientation() {
guard let connection = videoPreviewLayer?.connection else {
return
}
let previewLayerConnection: AVCaptureConnection = connection

guard previewLayerConnection.isVideoOrientationSupported else {
return
}
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ let package = Package(
dependencies: ["WalletConnectKMS", "WalletConnectUtils", "TestingUtils"]),
.target(
name: "TestingUtils",
dependencies: ["WalletConnectUtils", "WalletConnectKMS", "JSONRPC"],
dependencies: ["WalletConnectUtils", "WalletConnectKMS", "JSONRPC", "WalletConnectPairing"],
path: "Tests/TestingUtils"),
.testTarget(
name: "WalletConnectUtilsTests",
Expand Down
2 changes: 1 addition & 1 deletion Sources/Auth/Auth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class Auth {
account: config.account,
relayClient: Relay.instance)
}()

private static var config: Config?

private init() { }
Expand Down
2 changes: 0 additions & 2 deletions Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import WalletConnectUtils
import WalletConnectPairing
import WalletConnectRelay


/// WalletConnect Auth Client
///
/// Cannot be instantiated outside of the SDK
Expand Down Expand Up @@ -41,7 +40,6 @@ public class AuthClient {
/// An object that loggs SDK's errors and info messages
public let logger: ConsoleLogging


// MARK: - Private Properties

private var authResponsePublisherSubject = PassthroughSubject<(id: RPCID, result: Result<Cacao, AuthError>), Never>()
Expand Down
2 changes: 1 addition & 1 deletion Sources/Auth/AuthClientFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public struct AuthClientFactory {
let appPairService = AppPairService(networkingInteractor: networkingInteractor, kms: kms, pairingStorage: pairingStore)
let appRequestService = AppRequestService(networkingInteractor: networkingInteractor, kms: kms, appMetadata: metadata, logger: logger)
let messageSigner = MessageSigner(signer: Signer())
let appRespondSubscriber = AppRespondSubscriber(networkingInteractor: networkingInteractor, logger: logger, rpcHistory: history, signatureVerifier: messageSigner, messageFormatter: messageFormatter)
let appRespondSubscriber = AppRespondSubscriber(networkingInteractor: networkingInteractor, logger: logger, rpcHistory: history, signatureVerifier: messageSigner, messageFormatter: messageFormatter, pairingStorage: pairingStore)
let walletPairService = WalletPairService(networkingInteractor: networkingInteractor, kms: kms, pairingStorage: pairingStore)
let walletRequestSubscriber = WalletRequestSubscriber(networkingInteractor: networkingInteractor, logger: logger, kms: kms, messageFormatter: messageFormatter, address: account?.address)
let walletRespondService = WalletRespondService(networkingInteractor: networkingInteractor, logger: logger, kms: kms, rpcHistory: history)
Expand Down
18 changes: 17 additions & 1 deletion Sources/Auth/Services/App/AppRespondSubscriber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import Combine
import Foundation
import WalletConnectUtils
import JSONRPC
import WalletConnectPairing

class AppRespondSubscriber {
private let networkingInteractor: NetworkInteracting
private let pairingStorage: WCPairingStorage
private let logger: ConsoleLogging
private let rpcHistory: RPCHistory
private let signatureVerifier: MessageSignatureVerifying
Expand All @@ -17,12 +19,14 @@ class AppRespondSubscriber {
logger: ConsoleLogging,
rpcHistory: RPCHistory,
signatureVerifier: MessageSignatureVerifying,
messageFormatter: SIWEMessageFormatting) {
messageFormatter: SIWEMessageFormatting,
pairingStorage: WCPairingStorage) {
self.networkingInteractor = networkingInteractor
self.logger = logger
self.rpcHistory = rpcHistory
self.signatureVerifier = signatureVerifier
self.messageFormatter = messageFormatter
self.pairingStorage = pairingStorage
subscribeForResponse()
}

Expand All @@ -35,6 +39,7 @@ class AppRespondSubscriber {
let requestParams = request.params, request.method == "wc_authRequest"
else { return }

activatePairingIfNeeded(id: requestId)
networkingInteractor.unsubscribe(topic: subscriptionPayload.topic)

if let errorResponse = response.error,
Expand Down Expand Up @@ -62,4 +67,15 @@ class AppRespondSubscriber {

}.store(in: &publishers)
}

private func activatePairingIfNeeded(id: RPCID) {
guard let record = rpcHistory.get(recordId: id) else { return }
let pairingTopic = record.topic
guard var pairing = pairingStorage.getPairing(forTopic: pairingTopic) else { return }
if !pairing.active {
pairing.activate()
} else {
try? pairing.updateExpiry()
}
}
}
2 changes: 1 addition & 1 deletion Sources/Auth/Services/Common/NetworkingInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protocol NetworkInteracting {
func subscribe(topic: String) async throws
func unsubscribe(topic: String)
func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws
func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws
func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws
func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws
func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws
}
Expand Down
1 change: 0 additions & 1 deletion Sources/Auth/Types/Errors/Reason.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ protocol Reason {
var code: Int { get }
var message: String { get }
}

1 change: 0 additions & 1 deletion Sources/WalletConnectSign/Sign/SignClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ public final class SignClient {
return WalletConnectUtils.JsonRpcRecord(id: record.id, topic: record.topic, request: request, response: record.response, chainId: record.chainId)
}


#if DEBUG
/// Delete all stored data such as: pairings, sessions, keys
///
Expand Down
Loading

0 comments on commit bc9095a

Please sign in to comment.