Skip to content

Commit

Permalink
Merge pull request #438 from WalletConnect/feature/singleton-relay-#431
Browse files Browse the repository at this point in the history
[Relay] Relay Singleton instance
  • Loading branch information
flypaper0 authored Aug 17, 2022
2 parents 953df6a + 64b6d76 commit 5d25aa3
Show file tree
Hide file tree
Showing 24 changed files with 264 additions and 445 deletions.
3 changes: 2 additions & 1 deletion Example/DApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
url: "wallet.connect",
icons: ["https://avatars.githubusercontent.com/u/37784886"])

Sign.configure(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a", socketFactory: SocketFactory())
Relay.configure(projectId: "8ba9ee138960775e5231b70cc5ef1c3a", socketFactory: SocketFactory())
Sign.configure(metadata: metadata)

if CommandLine.arguments.contains("-cleanInstall") {
try? Sign.instance.cleanup()
Expand Down
8 changes: 4 additions & 4 deletions Example/ExampleApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
84CE645527A29D4D00142511 /* ResponseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE645427A29D4C00142511 /* ResponseViewController.swift */; };
84F568C2279582D200D0A289 /* Signer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F568C1279582D200D0A289 /* Signer.swift */; };
84F568C42795832A00D0A289 /* EthereumTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F568C32795832A00D0A289 /* EthereumTransaction.swift */; };
A50C036528AAD32200FE72D3 /* ClientDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50C036428AAD32200FE72D3 /* ClientDelegate.swift */; };
A50F3946288005B200064555 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50F3945288005B200064555 /* Types.swift */; };
A5629AA92876A23100094373 /* ChatService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AA82876A23100094373 /* ChatService.swift */; };
A5629ABD2876CBC000094373 /* ChatListModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AB82876CBC000094373 /* ChatListModule.swift */; };
Expand Down Expand Up @@ -126,7 +127,6 @@
A5D85228286333E300DAF5C3 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5D85227286333E300DAF5C3 /* Starscream */; };
A5E03DF52864651200888481 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DF42864651200888481 /* Starscream */; };
A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DF9286465C700888481 /* SignClientTests.swift */; };
A5E03DFB286465C700888481 /* ClientDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DF8286465C700888481 /* ClientDelegate.swift */; };
A5E03DFD286465D100888481 /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DFC286465D100888481 /* Stubs.swift */; };
A5E03DFF2864662500888481 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DFE2864662500888481 /* WalletConnect */; };
A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03E00286466EA00888481 /* WalletConnectChat */; };
Expand Down Expand Up @@ -205,6 +205,7 @@
84CE645427A29D4C00142511 /* ResponseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseViewController.swift; sourceTree = "<group>"; };
84F568C1279582D200D0A289 /* Signer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signer.swift; sourceTree = "<group>"; };
84F568C32795832A00D0A289 /* EthereumTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumTransaction.swift; sourceTree = "<group>"; };
A50C036428AAD32200FE72D3 /* ClientDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientDelegate.swift; sourceTree = "<group>"; };
A50F3945288005B200064555 /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
A5629AA82876A23100094373 /* ChatService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatService.swift; sourceTree = "<group>"; };
A5629AB82876CBC000094373 /* ChatListModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListModule.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -282,7 +283,6 @@
A5C2022A287EB89A007E3188 /* WelcomeInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeInteractor.swift; sourceTree = "<group>"; };
A5C2022C287EC3F0007E3188 /* RegisterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterService.swift; sourceTree = "<group>"; };
A5E03DED286464DB00888481 /* IntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A5E03DF8286465C700888481 /* ClientDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientDelegate.swift; sourceTree = "<group>"; };
A5E03DF9286465C700888481 /* SignClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignClientTests.swift; sourceTree = "<group>"; };
A5E03DFC286465D100888481 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = "<group>"; };
A5E03E02286466F400888481 /* ChatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -441,7 +441,7 @@
767DC83328997F7600080FA9 /* Helpers */ = {
isa = PBXGroup;
children = (
A5E03DF8286465C700888481 /* ClientDelegate.swift */,
A50C036428AAD32200FE72D3 /* ClientDelegate.swift */,
767DC83428997F8E00080FA9 /* EthSendTransaction.swift */,
);
path = Helpers;
Expand Down Expand Up @@ -1260,9 +1260,9 @@
buildActionMask = 2147483647;
files = (
767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */,
A5E03DFB286465C700888481 /* ClientDelegate.swift in Sources */,
A5E03E03286466F400888481 /* ChatTests.swift in Sources */,
7694A5262874296A0001257E /* RegistryTests.swift in Sources */,
A50C036528AAD32200FE72D3 /* ClientDelegate.swift in Sources */,
A5E03E0D28646AD200888481 /* RelayClientEndToEndTests.swift in Sources */,
A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */,
A5E03E0F28646D8A00888481 /* WebSocketFactory.swift in Sources */,
Expand Down
3 changes: 2 additions & 1 deletion Example/ExampleApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
url: "example.wallet",
icons: ["https://avatars.githubusercontent.com/u/37784886"])

Sign.configure(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a", socketFactory: SocketFactory())
Relay.configure(projectId: "8ba9ee138960775e5231b70cc5ef1c3a", socketFactory: SocketFactory())
Sign.configure(metadata: metadata)

if CommandLine.arguments.contains("-cleanInstall") {
try? Sign.instance.cleanup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ final class SessionDetailViewController: UIHostingController<SessionDetailView>

private let viewModel: SessionDetailViewModel

init(session: Session, client: Sign) {
init(session: Session, client: SignClient) {
self.viewModel = SessionDetailViewModel(session: session, client: client)
super.init(rootView: SessionDetailView(viewModel: viewModel))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WalletConnectSign
@MainActor
final class SessionDetailViewModel: ObservableObject {
private let session: Session
private let client: Sign
private let client: SignClient

enum Fields {
case accounts
Expand All @@ -18,7 +18,7 @@ final class SessionDetailViewModel: ObservableObject {
@Published var pingSuccess: Bool = false
@Published var pingFailed: Bool = false

init(session: Session, client: Sign) {
init(session: Session, client: SignClient) {
self.session = session
self.client = client
self.namespaces = session.namespaces
Expand Down
10 changes: 6 additions & 4 deletions Example/IntegrationTests/Relay/RelayClientEndToEndTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,16 @@ final class RelayClientEndToEndTests: XCTestCase {
expectationA.assertForOverFulfill = false
expectationB.assertForOverFulfill = false

relayA.onMessage = { topic, payload in
relayA.messagePublisher.sink { topic, payload in
(subscriptionATopic, subscriptionAPayload) = (topic, payload)
expectationA.fulfill()
}
relayB.onMessage = { topic, payload in
}.store(in: &publishers)

relayB.messagePublisher.sink { topic, payload in
(subscriptionBTopic, subscriptionBPayload) = (topic, payload)
expectationB.fulfill()
}
}.store(in: &publishers)

relayA.socketConnectionStatusPublisher.sink { _ in
relayA.publish(topic: randomTopic, payload: payloadA, tag: 0, onNetworkAcknowledge: { error in
XCTAssertNil(error)
Expand Down
82 changes: 46 additions & 36 deletions Example/IntegrationTests/Sign/Helpers/ClientDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import Foundation
@testable import WalletConnectSign
import Combine

class ClientDelegate: SignClientDelegate {
func didChangeSocketConnectionStatus(_ status: SocketConnectionStatus) {
onConnected?()
}
class ClientDelegate {

var client: SignClient
var onSessionSettled: ((Session) -> Void)?
Expand All @@ -15,43 +13,55 @@ class ClientDelegate: SignClientDelegate {
var onSessionRejected: ((Session.Proposal, Reason) -> Void)?
var onSessionDelete: (() -> Void)?
var onSessionUpdateNamespaces: ((String, [String: SessionNamespace]) -> Void)?
var onSessionUpdateEvents: ((String, Set<String>) -> Void)?
var onSessionExtend: ((String, Date) -> Void)?
var onEventReceived: ((Session.Event, String) -> Void)?
var onPairingUpdate: ((Pairing) -> Void)?

internal init(client: SignClient) {
private var publishers = Set<AnyCancellable>()

init(client: SignClient) {
self.client = client
client.delegate = self
setupSubscriptions()
}

func didReject(proposal: Session.Proposal, reason: Reason) {
onSessionRejected?(proposal, reason)
}
func didSettle(session: Session) {
onSessionSettled?(session)
}
func didReceive(sessionProposal: Session.Proposal) {
onSessionProposal?(sessionProposal)
}
func didReceive(sessionRequest: Request) {
onSessionRequest?(sessionRequest)
}
func didDelete(sessionTopic: String, reason: Reason) {
onSessionDelete?()
}
func didUpdate(sessionTopic: String, namespaces: [String: SessionNamespace]) {
onSessionUpdateNamespaces?(sessionTopic, namespaces)
}
func didExtend(sessionTopic: String, to date: Date) {
onSessionExtend?(sessionTopic, date)
}
func didReceive(event: Session.Event, sessionTopic: String, chainId: Blockchain?) {
onEventReceived?(event, sessionTopic)
}
func didReceive(sessionResponse: Response) {
onSessionResponse?(sessionResponse)
}
private func setupSubscriptions() {
client.sessionSettlePublisher.sink { session in
self.onSessionSettled?(session)
}.store(in: &publishers)

client.socketConnectionStatusPublisher.sink { _ in
self.onConnected?()
}.store(in: &publishers)

client.sessionProposalPublisher.sink { proposal in
self.onSessionProposal?(proposal)
}.store(in: &publishers)

client.sessionRequestPublisher.sink { request in
self.onSessionRequest?(request)
}.store(in: &publishers)

client.sessionResponsePublisher.sink { response in
self.onSessionResponse?(response)
}.store(in: &publishers)

func didDisconnect() {}
client.sessionRejectionPublisher.sink { (proposal, reason) in
self.onSessionRejected?(proposal, reason)
}.store(in: &publishers)

client.sessionDeletePublisher.sink { _ in
self.onSessionDelete?()
}.store(in: &publishers)

client.sessionUpdatePublisher.sink { (topic, namespaces) in
self.onSessionUpdateNamespaces?(topic, namespaces)
}.store(in: &publishers)

client.sessionEventPublisher.sink { (event, topic, _) in
self.onEventReceived?(event, topic)
}.store(in: &publishers)

client.sessionExtendPublisher.sink { (topic, date) in
self.onSessionExtend?(topic, date)
}.store(in: &publishers)
}
}
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let package = Package(
targets: ["Chat"]),
.library(
name: "WalletConnectRouter",
targets: ["WalletConnectRouter"]),
targets: ["WalletConnectRouter"])
],
dependencies: [
.package(url: "https://github.com/flypaper0/Web3.swift", .branch("feature/eip-155"))
Expand Down
1 change: 0 additions & 1 deletion Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,3 @@ class AuthClient {
}
}
}

2 changes: 1 addition & 1 deletion Sources/Auth/Services/Signer/MessageSigner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ protocol MessageSigning {
func sign(message: String, privateKey: Data) throws -> String
}

struct MessageSigner: MessageSignatureVerifying & MessageSigning {
struct MessageSigner: MessageSignatureVerifying, MessageSigning {

enum Errors: Error {
case signatureValidationFailed
Expand Down
14 changes: 7 additions & 7 deletions Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class WalletRequestSubscriber {
private let address: String
private var publishers = [AnyCancellable]()
private let messageFormatter: SIWEMessageFormatting
var onRequest: ((_ id: RPCID, _ message: String)->Void)?
var onRequest: ((_ id: RPCID, _ message: String) -> Void)?

init(networkingInteractor: NetworkInteracting,
logger: ConsoleLogging,
messageFormatter: SIWEMessageFormatting,
Expand All @@ -21,27 +21,27 @@ class WalletRequestSubscriber {
self.messageFormatter = messageFormatter
subscribeForRequest()
}

private func subscribeForRequest() {
networkingInteractor.requestPublisher.sink { [unowned self] subscriptionPayload in
guard
let requestId = subscriptionPayload.request.id,
subscriptionPayload.request.method == "wc_authRequest" else { return }

do {
guard let authRequestParams = try subscriptionPayload.request.params?.get(AuthRequestParams.self) else { return logger.debug("Malformed auth request params")
}

let message = messageFormatter.formatMessage(
from: authRequestParams.payloadParams,
address: address
)

onRequest?(requestId, message)
} catch {
logger.debug(error)
}
}.store(in: &publishers)
}

}
7 changes: 5 additions & 2 deletions Sources/Chat/NetworkingInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class NetworkingInteractor: NetworkInteracting {
private let responsePublisherSubject = PassthroughSubject<ChatResponse, Never>()
var socketConnectionStatusPublisher: AnyPublisher<SocketConnectionStatus, Never>

private var publishers = Set<AnyCancellable>()

init(relayClient: RelayClient,
serializer: Serializing,
logger: ConsoleLogging,
Expand All @@ -49,9 +51,10 @@ class NetworkingInteractor: NetworkInteracting {
self.jsonRpcHistory = jsonRpcHistory
self.logger = logger
self.socketConnectionStatusPublisher = relayClient.socketConnectionStatusPublisher
relayClient.onMessage = { [unowned self] topic, message in

relayClient.messagePublisher.sink { [unowned self] (topic, message) in
manageSubscription(topic, message)
}
}.store(in: &publishers)
}

func request(_ request: JSONRPCRequest<ChatRequestParams>, topic: String, envelopeType: Envelope.EnvelopeType) async throws {
Expand Down
34 changes: 34 additions & 0 deletions Sources/WalletConnectRelay/Relay.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Foundation

public class Relay {

public static var instance: RelayClient = {
guard let config = Relay.config else {
fatalError("Error - you must call Relay.configure(_:) before accessing the shared instance.")
}
return RelayClient(
relayHost: config.relayHost,
projectId: config.projectId,
socketFactory: config.socketFactory,
socketConnectionType: config.socketConnectionType
)
}()

private static var config: Config?

private init() { }

static public func configure(
relayHost: String = "relay.walletconnect.com",
projectId: String,
socketFactory: WebSocketFactory,
socketConnectionType: SocketConnectionType = .automatic
) {
Relay.config = Relay.Config(
relayHost: relayHost,
projectId: projectId,
socketFactory: socketFactory,
socketConnectionType: socketConnectionType
)
}
}
12 changes: 9 additions & 3 deletions Sources/WalletConnectRelay/RelayClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ public final class RelayClient {

static let historyIdentifier = "com.walletconnect.sdk.relayer_client.subscription_json_rpc_record"

public var onMessage: ((String, String) -> Void)?

let defaultTtl = 6*Time.hour
var subscriptions: [String: String] = [:]

public var messagePublisher: AnyPublisher<(topic: String, message: String), Never> {
messagePublisherSubject.eraseToAnyPublisher()
}

public var socketConnectionStatusPublisher: AnyPublisher<SocketConnectionStatus, Never> {
socketConnectionStatusPublisherSubject.eraseToAnyPublisher()
}

private let messagePublisherSubject = PassthroughSubject<(topic: String, message: String), Never>()
private let socketConnectionStatusPublisherSubject = PassthroughSubject<SocketConnectionStatus, Never>()

private let subscriptionResponsePublisherSubject = PassthroughSubject<(RPCID?, String), Never>()
Expand All @@ -42,6 +46,8 @@ public final class RelayClient {

private let concurrentQueue = DispatchQueue(label: "com.walletconnect.sdk.relay_client", attributes: .concurrent)

// MARK: - Initialization

init(
dispatcher: Dispatching,
logger: ConsoleLogging,
Expand Down Expand Up @@ -227,7 +233,7 @@ public final class RelayClient {
do {
try rpcHistory.set(request, forTopic: params.data.topic, emmitedBy: .remote)
try acknowledgeRequest(request)
onMessage?(params.data.topic, params.data.message)
messagePublisherSubject.send((params.data.topic, params.data.message))
} catch {
logger.error("[RelayClient] RPC History 'set()' error: \(error)")
}
Expand Down
10 changes: 10 additions & 0 deletions Sources/WalletConnectRelay/RelayConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation

extension Relay {
struct Config {
let relayHost: String
let projectId: String
let socketFactory: WebSocketFactory
let socketConnectionType: SocketConnectionType
}
}
Loading

0 comments on commit 5d25aa3

Please sign in to comment.