diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift index 226f5b80d..0216a3db6 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift @@ -20,18 +20,14 @@ final class SessionProposalInteractor { let supportedChains = [Blockchain("eip155:1")!, Blockchain("eip155:137")!] let supportedAccounts = [Account(blockchain: Blockchain("eip155:1")!, address: ETHSigner.address)!, Account(blockchain: Blockchain("eip155:137")!, address: ETHSigner.address)!] */ - do { - let sessionNamespaces = try AutoNamespaces.build( - sessionProposal: proposal, - chains: Array(supportedChains), - methods: Array(supportedMethods), - events: Array(supportedEvents), - accounts: supportedAccounts - ) - try await Web3Wallet.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties) - } catch { - print(error) - } + let sessionNamespaces = try AutoNamespaces.build( + sessionProposal: proposal, + chains: Array(supportedChains), + methods: Array(supportedMethods), + events: Array(supportedEvents), + accounts: supportedAccounts + ) + try await Web3Wallet.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties) } func reject(proposal: Session.Proposal) async throws { diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift index 117db225c..ad02dd7a4 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift @@ -11,6 +11,9 @@ final class SessionProposalPresenter: ObservableObject { let sessionProposal: Session.Proposal let verified: Bool? + @Published var showError = false + @Published var errorMessage = "Error" + private var disposeBag = Set() init( @@ -30,14 +33,24 @@ final class SessionProposalPresenter: ObservableObject { @MainActor func onApprove() async throws { - try await interactor.approve(proposal: sessionProposal, account: importAccount.account) - router.dismiss() + do { + try await interactor.approve(proposal: sessionProposal, account: importAccount.account) + router.dismiss() + } catch { + errorMessage = error.localizedDescription + showError.toggle() + } } @MainActor func onReject() async throws { - try await interactor.reject(proposal: sessionProposal) - router.dismiss() + do { + try await interactor.reject(proposal: sessionProposal) + router.dismiss() + } catch { + errorMessage = error.localizedDescription + showError.toggle() + } } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalView.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalView.swift index 97717d9b5..8082ce1ee 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalView.swift @@ -146,6 +146,9 @@ struct SessionProposalView: View { Spacer() } } + .alert(presenter.errorMessage, isPresented: $presenter.showError) { + Button("OK", role: .cancel) {} + } .edgesIgnoringSafeArea(.all) } //private func sessionProposalView(chain: String) -> some View { diff --git a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift index 402a9144b..dd77da949 100644 --- a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift @@ -9,6 +9,7 @@ final class ApproveEngine { case pairingNotFound case sessionNotFound case agreementMissingOrInvalid + case networkNotConnected } var onSessionProposal: ((Session.Proposal, VerifyContext?) -> Void)? @@ -63,6 +64,11 @@ final class ApproveEngine { guard let payload = try proposalPayloadsStore.get(key: proposerPubKey) else { throw Errors.wrongRequestParams } + + let networkConnectionStatus = await resolveNetworkConnectionStatus() + guard networkConnectionStatus == .connected else { + throw Errors.networkNotConnected + } let proposal = payload.request let pairingTopic = payload.topic @@ -378,4 +384,28 @@ private extension ApproveEngine { } onSessionSettle?(session.publicRepresentation()) } + + func resolveNetworkConnectionStatus() async -> NetworkConnectionStatus { + return await withCheckedContinuation { continuation in + let cancellable = networkingInteractor.networkConnectionStatusPublisher.sink { value in + continuation.resume(returning: value) + } + + Task(priority: .high) { + await withTaskCancellationHandler { + cancellable.cancel() + } onCancel: { } + } + } + } +} + +// MARK: - LocalizedError +extension ApproveEngine.Errors: LocalizedError { + var errorDescription: String? { + switch self { + case .networkNotConnected: return "Action failed. You seem to be offline" + default: return "" + } + } }