Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#168 completion errors on public methods #191

Merged
merged 11 commits into from
May 5, 2022
13 changes: 11 additions & 2 deletions Example/DApp/ Accounts/AccountsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,17 @@ final class AccountsViewController: UIViewController, UITableViewDataSource, UIT

@objc
private func disconnect() {
client.disconnect(topic: session.topic, reason: Reason(code: 0, message: "disconnect"))
onDisconnect?()
Task {
do {
try await client.disconnect(topic: session.topic, reason: Reason(code: 0, message: "disconnect"))
DispatchQueue.main.async { [weak self] in
self?.onDisconnect?()
}
} catch {
print(error)
//show failure alert
}
}
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
Expand Down
13 changes: 11 additions & 2 deletions Example/DApp/AccountRequest/AccountRequestViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ class AccountRequestViewController: UIViewController, UITableViewDelegate, UITab


let request = Request(topic: session.topic, method: method, params: requestParams, chainId: Blockchain(chainId)!)
client.request(params: request)
presentConfirmationAlert()
Task {
do {
try await client.request(params: request)
DispatchQueue.main.async { [weak self] in
self?.presentConfirmationAlert()
}
} catch {
print(error)
//show failure alert
}
}
}

private func presentConfirmationAlert() {
Expand Down
14 changes: 11 additions & 3 deletions Example/ExampleApp/Wallet/WalletViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,17 @@ extension WalletViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let item = sessionItems[indexPath.row]
client.disconnect(topic: item.topic, reason: Reason(code: 0, message: "disconnect"))
sessionItems.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
Task {
do {
try await client.disconnect(topic: item.topic, reason: Reason(code: 0, message: "disconnect"))
DispatchQueue.main.async { [weak self] in
self?.sessionItems.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
} catch {
print(error)
}
}
}
}

Expand Down
13 changes: 7 additions & 6 deletions Sources/Relayer/Dispatching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ final class Dispatcher: NSObject, Dispatching {
}

func send(_ string: String, completion: @escaping (Error?) -> Void) {
if socket.isConnected {
self.socket.send(string, completionHandler: completion)
//TODO - enqueue if fails
} else {
textFramesQueue.enqueue(string)
}
//TODO - add policy for retry and "single try"
// if socket.isConnected {
self.socket.send(string, completionHandler: completion)
//TODO - enqueue if fails
// } else {
// textFramesQueue.enqueue(string)
// }
}

func connect() throws {
Expand Down
27 changes: 24 additions & 3 deletions Sources/Relayer/Relayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,32 @@ public final class Relayer {
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)
let request = JSONRPCRequest<RelayJSONRPC.PublishParams>(method: RelayJSONRPC.Method.publish.rawValue, params: params)
let requestJson = try! request.json()
logger.debug("Publishing Payload on Topic: \(topic)")
return try await withCheckedThrowingContinuation { continuation in
dispatcher.send(requestJson) { error in
if let error = error {
continuation.resume(throwing: error)
return
}
continuation.resume(returning: ())
}
}
}

/// Completes with an acknowledgement from the relay network.
@discardableResult public func publish(
topic: String,
payload: String,
prompt: Bool = false,
completion: @escaping ((Error?) -> ())) -> Int64 {
onNetworkAcknowledge: @escaping ((Error?) -> ())) -> Int64 {
let params = RelayJSONRPC.PublishParams(topic: topic, message: payload, ttl: defaultTtl, prompt: prompt)
let request = JSONRPCRequest<RelayJSONRPC.PublishParams>(method: RelayJSONRPC.Method.publish.rawValue, params: params)
let requestJson = try! request.json()
Expand All @@ -94,14 +115,14 @@ public final class Relayer {
if let error = error {
self?.logger.debug("Failed to Publish Payload, error: \(error)")
cancellable?.cancel()
completion(error)
onNetworkAcknowledge(error)
}
}
cancellable = requestAcknowledgePublisher
.filter {$0.id == request.id}
.sink { (subscriptionResponse) in
cancellable?.cancel()
completion(nil)
onNetworkAcknowledge(nil)
}
return request.id
}
Expand Down
34 changes: 17 additions & 17 deletions Sources/WalletConnect/Engine/PairingEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class PairingEngine {
var onSessionRejected: ((Session.Proposal, SessionType.Reason)->())?

private let proposalPayloadsStore: KeyValueStore<WCRequestSubscriptionPayload>
private let relayer: WalletConnectRelaying
private let networkingInteractor: NetworkInteracting
private let kms: KeyManagementServiceProtocol
private let pairingStore: WCPairingStorage
private let sessionToPairingTopic: KeyValueStore<String>
Expand All @@ -19,15 +19,15 @@ final class PairingEngine {
private let logger: ConsoleLogging
private let topicInitializer: () -> String

init(relay: WalletConnectRelaying,
init(networkingInteractor: NetworkInteracting,
kms: KeyManagementServiceProtocol,
pairingStore: WCPairingStorage,
sessionToPairingTopic: KeyValueStore<String>,
metadata: AppMetadata,
logger: ConsoleLogging,
topicGenerator: @escaping () -> String = String.generateTopic,
proposalPayloadsStore: KeyValueStore<WCRequestSubscriptionPayload> = KeyValueStore<WCRequestSubscriptionPayload>(defaults: RuntimeKeyValueStorage(), identifier: StorageDomainIdentifiers.proposals.rawValue)) {
self.relayer = relay
self.networkingInteractor = networkingInteractor
self.kms = kms
self.metadata = metadata
self.pairingStore = pairingStore
Expand All @@ -38,7 +38,7 @@ final class PairingEngine {
setUpWCRequestHandling()
setupExpirationHandling()
restoreSubscriptions()
relayer.onPairingResponse = { [weak self] in
networkingInteractor.onPairingResponse = { [weak self] in
self?.handleResponse($0)
}
}
Expand All @@ -65,7 +65,7 @@ final class PairingEngine {
let pairing = WCPairing(topic: topic)
let uri = WalletConnectURI(topic: topic, symKey: symKey.hexRepresentation, relay: pairing.relay)
pairingStore.setPairing(pairing)
relayer.subscribe(topic: topic)
networkingInteractor.subscribe(topic: topic)
return uri
}
func propose(pairingTopic: String, namespaces: Set<Namespace>, relay: RelayProtocolOptions, completion: @escaping ((Error?) -> ())) {
Expand All @@ -78,7 +78,7 @@ final class PairingEngine {
relays: [relay],
proposer: proposer,
namespaces: namespaces)
relayer.requestNetworkAck(.wcSessionPropose(proposal), onTopic: pairingTopic) { [unowned self] error in
networkingInteractor.requestNetworkAck(.wcSessionPropose(proposal), onTopic: pairingTopic) { [unowned self] error in
logger.debug("Received propose acknowledgement")
completion(error)
}
Expand All @@ -92,7 +92,7 @@ final class PairingEngine {
let symKey = try! SymmetricKey(hex: uri.symKey) // FIXME: Malformed QR code from external source can crash the SDK
try! kms.setSymmetricKey(symKey, for: pairing.topic)
pairing.activate()
relayer.subscribe(topic: pairing.topic)
networkingInteractor.subscribe(topic: pairing.topic)
pairingStore.setPairing(pairing)
}

Expand All @@ -101,7 +101,7 @@ final class PairingEngine {
logger.debug("Could not find pairing to ping for topic \(topic)")
return
}
relayer.request(.wcPairingPing, onTopic: topic) { [unowned self] result in
networkingInteractor.requestPeerResponse(.wcPairingPing, onTopic: topic) { [unowned self] result in
switch result {
case .success(_):
logger.debug("Did receive ping response")
Expand All @@ -117,7 +117,7 @@ final class PairingEngine {
return
}
proposalPayloadsStore.delete(forKey: proposal.proposer.publicKey)
relayer.respondError(for: payload, reason: reason)
networkingInteractor.respondError(for: payload, reason: reason)
// todo - delete pairing if inactive
}

Expand All @@ -135,7 +135,7 @@ final class PairingEngine {
do {
agreementKey = try kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey)
} catch {
relayer.respondError(for: payload, reason: .missingOrInvalid("agreement keys"))
networkingInteractor.respondError(for: payload, reason: .missingOrInvalid("agreement keys"))
return nil
}
//todo - extend pairing
Expand All @@ -145,14 +145,14 @@ final class PairingEngine {
guard let relay = proposal.relays.first else {return nil}
let proposeResponse = SessionType.ProposeResponse(relay: relay, responderPublicKey: selfPublicKey.hexRepresentation)
let response = JSONRPCResponse<AnyCodable>(id: payload.wcRequest.id, result: AnyCodable(proposeResponse))
relayer.respond(topic: payload.topic, response: .response(response)) { _ in }
networkingInteractor.respond(topic: payload.topic, response: .response(response)) { _ in }
return (sessionTopic, proposal)
}

//MARK: - Private

private func setUpWCRequestHandling() {
relayer.wcRequestPublisher.sink { [unowned self] subscriptionPayload in
networkingInteractor.wcRequestPublisher.sink { [unowned self] subscriptionPayload in
switch subscriptionPayload.wcRequest.params {
case .pairingPing(_):
wcPairingPing(subscriptionPayload)
Expand All @@ -171,22 +171,22 @@ final class PairingEngine {
}

private func wcPairingPing(_ payload: WCRequestSubscriptionPayload) {
relayer.respondSuccess(for: payload)
networkingInteractor.respondSuccess(for: payload)
}

private func restoreSubscriptions() {
relayer.transportConnectionPublisher
networkingInteractor.transportConnectionPublisher
.sink { [unowned self] (_) in
let topics = pairingStore.getAll()
.map{$0.topic}
topics.forEach{relayer.subscribe(topic: $0)}
topics.forEach{networkingInteractor.subscribe(topic: $0)}
}.store(in: &publishers)
}

private func setupExpirationHandling() {
pairingStore.onPairingExpiration = { [weak self] pairing in
self?.kms.deleteSymmetricKey(for: pairing.topic)
self?.relayer.unsubscribe(topic: pairing.topic)
self?.networkingInteractor.unsubscribe(topic: pairing.topic)
}
}

Expand Down Expand Up @@ -237,7 +237,7 @@ final class PairingEngine {
case .error(let error):
if !pairing.active {
kms.deleteSymmetricKey(for: pairing.topic)
relayer.unsubscribe(topic: pairing.topic)
networkingInteractor.unsubscribe(topic: pairing.topic)
pairingStore.delete(topic: pairingTopic)
}
logger.debug("session propose has been rejected")
Expand Down
Loading