From 519033c90d1e328734cc3eea26a50592559d4a68 Mon Sep 17 00:00:00 2001 From: skibitsky Date: Mon, 15 Apr 2024 18:40:39 +0300 Subject: [PATCH 1/2] Include pairing topic in ConnectedData and connection optimisation --- WalletConnectSharp.Sign/Engine.cs | 91 +++++++++++-------- .../Models/Engine/ConnectedData.cs | 37 ++++---- 2 files changed, 75 insertions(+), 53 deletions(-) diff --git a/WalletConnectSharp.Sign/Engine.cs b/WalletConnectSharp.Sign/Engine.cs index 8fc9290..0029197 100644 --- a/WalletConnectSharp.Sign/Engine.cs +++ b/WalletConnectSharp.Sign/Engine.cs @@ -416,7 +416,7 @@ public async Task Connect(ConnectOptions options) var sessionProperties = options.SessionProperties; var relays = options.Relays; var topic = options.PairingTopic; - string uri = ""; + var uri = string.Empty; var active = false; if (!string.IsNullOrEmpty(topic)) @@ -428,9 +428,9 @@ public async Task Connect(ConnectOptions options) if (string.IsNullOrEmpty(topic) || !active) { - var CreatePairing = await this.Client.Core.Pairing.Create(); - topic = CreatePairing.Topic; - uri = CreatePairing.Uri; + var newPairing = await Client.Core.Pairing.Create(); + topic = newPairing.Topic; + uri = newPairing.Uri; } var publicKey = await this.Client.Core.Crypto.GenerateKeyPair(); @@ -438,20 +438,49 @@ public async Task Connect(ConnectOptions options) { RequiredNamespaces = requiredNamespaces, Relays = relays != null - ? new[] { relays } - : new[] { new ProtocolOptions() { Protocol = RelayProtocols.Default } }, + ? [relays] + : [new ProtocolOptions() { Protocol = RelayProtocols.Default }], Proposer = new Participant() { PublicKey = publicKey, Metadata = this.Client.Metadata }, OptionalNamespaces = optionalNamespaces, SessionProperties = sessionProperties, }; TaskCompletionSource approvalTask = new TaskCompletionSource(); - this.SessionConnected += async (sender, session) => + + SessionConnected += OnSessionConnected; + SessionConnectionErrored += OnSessionConnectionErrored; + + if (string.IsNullOrWhiteSpace(topic)) + { + throw WalletConnectException.FromType(ErrorType.NO_MATCHING_KEY, $"connect() pairing topic: {topic}"); + } + + var id = await MessageHandler.SendRequest(topic, proposal); + + var expiry = Clock.CalculateExpiry(options.Expiry); + + await PrivateThis.SetProposal(id, new ProposalStruct() { - logger.Log("Got session_connect event for session struct"); + Expiry = expiry, + Id = id, + Proposer = proposal.Proposer, + Relays = proposal.Relays, + RequiredNamespaces = proposal.RequiredNamespaces, + OptionalNamespaces = proposal.OptionalNamespaces, + SessionProperties = proposal.SessionProperties + }); + + return new ConnectedData(uri, topic, approvalTask.Task); + + async void OnSessionConnected(object sender, SessionStruct session) + { + if (session.PairingTopic != topic) + { + return; + } + if (approvalTask.Task.IsCompleted) { - logger.Log("approval already received though, skipping"); return; } @@ -462,44 +491,32 @@ public async Task Connect(ConnectOptions options) if (!string.IsNullOrWhiteSpace(topic)) { - await this.Client.Core.Pairing.UpdateMetadata(topic, session.Peer.Metadata); + await Client.Core.Pairing.UpdateMetadata(topic, session.Peer.Metadata); } + SessionConnected -= OnSessionConnected; + SessionConnectionErrored -= OnSessionConnectionErrored; + approvalTask.SetResult(completeSession); - }; + } - this.SessionConnectionErrored += (sender, exception) => + void OnSessionConnectionErrored(object sender, Exception exception) { if (approvalTask.Task.IsCompleted) + { return; + } if (exception == null) + { return; - - approvalTask.SetException(exception); - }; - - if (string.IsNullOrWhiteSpace(topic)) - { - throw WalletConnectException.FromType(ErrorType.NO_MATCHING_KEY, $"connect() pairing topic: {topic}"); - } - - var id = await MessageHandler.SendRequest(topic, proposal); - - var expiry = Clock.CalculateExpiry(options.Expiry); + } - await PrivateThis.SetProposal(id, new ProposalStruct() - { - Expiry = expiry, - Id = id, - Proposer = proposal.Proposer, - Relays = proposal.Relays, - RequiredNamespaces = proposal.RequiredNamespaces, - OptionalNamespaces = proposal.OptionalNamespaces, - SessionProperties = proposal.SessionProperties, - }); + SessionConnected -= OnSessionConnected; + SessionConnectionErrored -= OnSessionConnectionErrored; - return new ConnectedData() { Uri = uri, Approval = approvalTask.Task }; + approvalTask.SetException(exception); + } } /// @@ -569,7 +586,8 @@ public async Task Approve(ApproveParams @params) Relay = new ProtocolOptions() { Protocol = relayProtocol ?? "irn" }, Namespaces = namespaces, Controller = new Participant() { PublicKey = selfPublicKey, Metadata = this.Client.Metadata }, - Expiry = Clock.CalculateExpiry(SessionExpiry) + Expiry = Clock.CalculateExpiry(SessionExpiry), + PairingTopic = pairingTopic }; await this.Client.Core.Relayer.Subscribe(sessionTopic); @@ -595,6 +613,7 @@ public async Task Approve(ApproveParams @params) Expiry = sessionSettle.Expiry, Namespaces = sessionSettle.Namespaces, Relay = sessionSettle.Relay, + PairingTopic = pairingTopic, RequiredNamespaces = requiredNamespaces, }; diff --git a/WalletConnectSharp.Sign/Models/Engine/ConnectedData.cs b/WalletConnectSharp.Sign/Models/Engine/ConnectedData.cs index ff4d30a..4d825c9 100644 --- a/WalletConnectSharp.Sign/Models/Engine/ConnectedData.cs +++ b/WalletConnectSharp.Sign/Models/Engine/ConnectedData.cs @@ -1,23 +1,26 @@ -using System.Threading.Tasks; +namespace WalletConnectSharp.Sign.Models.Engine; -namespace WalletConnectSharp.Sign.Models.Engine +/// +/// A class that representing a pending session proposal. Includes a URI that can be given to a +/// wallet app out-of-band and an Approval Task that can be awaited. +/// +public class ConnectedData(string uri, string pairingTopic, Task approval) { /// - /// A class that representing a pending session proposal. Includes a URI that can be given to a - /// wallet app out-of-band and an Approval Task that can be awaited. + /// The URI that can be used to retrieve the submitted session proposal. This should be shared + /// SECURELY out-of-band to a wallet supporting the SDK. /// - public class ConnectedData - { - /// - /// The URI that can be used to retrieve the submitted session proposal. This should be shared - /// SECURELY out-of-band to a wallet supporting the SDK - /// - public string Uri; + public string Uri { get; private set; } = uri; - /// - /// A task that will resolve to an approved session. If the session proposal is rejected, then this - /// task will throw an exception. - /// - public Task Approval; - } + /// + /// Pairing is a topic encrypted by a symmetric key shared through a URI between two clients with + /// the sole purpose of communicating session proposals. + /// + public string PairingTopic { get; private set; } = pairingTopic; + + /// + /// A task that will resolve to an approved session. If the session proposal is rejected, then this + /// task will throw an exception. + /// + public Task Approval { get; private set; } = approval; } From 936624be973bd46fb449bbee83dd12a7d2ed042d Mon Sep 17 00:00:00 2001 From: skibitsky Date: Mon, 15 Apr 2024 18:55:48 +0300 Subject: [PATCH 2/2] Version bump --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index bb1252a..8b1e626 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 2.3.2 + 2.3.3 net6.0;net7.0;net8.0;netstandard2.1; true