diff --git a/WalletConnectSharp.Sign/Controllers/AddressProvider.cs b/WalletConnectSharp.Sign/Controllers/AddressProvider.cs index b5b42e1..e942d54 100644 --- a/WalletConnectSharp.Sign/Controllers/AddressProvider.cs +++ b/WalletConnectSharp.Sign/Controllers/AddressProvider.cs @@ -1,6 +1,4 @@ -using Newtonsoft.Json; -using WalletConnectSharp.Common.Logging; -using WalletConnectSharp.Sign.Interfaces; +using WalletConnectSharp.Sign.Interfaces; using WalletConnectSharp.Sign.Models; using WalletConnectSharp.Sign.Models.Engine.Events; @@ -8,6 +6,8 @@ namespace WalletConnectSharp.Sign.Controllers; public class AddressProvider : IAddressProvider { + private bool _disposed; + public struct DefaultData { public SessionStruct Session; @@ -91,7 +91,7 @@ public AddressProvider(ISignClient client) // set the first connected session to the default one client.SessionConnected += ClientOnSessionConnected; client.SessionDeleted += ClientOnSessionDeleted; - client.SessionUpdated += ClientOnSessionUpdated; + client.SessionUpdateRequest += ClientOnSessionUpdated; client.SessionApproved += ClientOnSessionConnected; } @@ -119,6 +119,7 @@ private async void ClientOnSessionUpdated(object sender, SessionEvent e) { if (DefaultSession.Topic == e.Topic) { + DefaultSession = Sessions.Get(e.Topic); await UpdateDefaultChainIdAndNamespaceAsync(); } } @@ -180,20 +181,27 @@ private async Task UpdateDefaultChainIdAndNamespaceAsync() } } - public Caip25Address CurrentAddress(string @namespace = null, SessionStruct session = default) - { - @namespace ??= DefaultNamespace; - if (string.IsNullOrWhiteSpace(session.Topic)) // default - session = DefaultSession; - - return session.CurrentAddress(@namespace); - } - public async Task InitAsync() { await this.LoadDefaults(); } + public async Task SetDefaultNamespaceAsync(string @namespace) + { + if (string.IsNullOrWhiteSpace(@namespace)) + { + throw new ArgumentNullException(nameof(@namespace)); + } + + if (!DefaultSession.Namespaces.ContainsKey(@namespace)) + { + throw new InvalidOperationException($"Namespace {@namespace} is not available in the current session"); + } + + DefaultNamespace = @namespace; + await SaveDefaults(); + } + public async Task SetDefaultChainIdAsync(string chainId) { if (string.IsNullOrWhiteSpace(chainId)) @@ -210,7 +218,18 @@ public async Task SetDefaultChainIdAsync(string chainId) await SaveDefaults(); } - public Caip25Address[] AllAddresses(string @namespace = null, SessionStruct session = default) + public Caip25Address CurrentAddress(string chainId = null, SessionStruct session = default) + { + chainId ??= DefaultChainId; + if (string.IsNullOrWhiteSpace(session.Topic)) + { + session = DefaultSession; + } + + return session.CurrentAddress(chainId); + } + + public IEnumerable AllAddresses(string @namespace = null, SessionStruct session = default) { @namespace ??= DefaultNamespace; if (string.IsNullOrWhiteSpace(session.Topic)) // default @@ -218,17 +237,33 @@ public Caip25Address[] AllAddresses(string @namespace = null, SessionStruct sess return session.AllAddresses(@namespace); } - + public void Dispose() { - _client.SessionConnected -= ClientOnSessionConnected; - _client.SessionDeleted -= ClientOnSessionDeleted; - _client.SessionUpdated -= ClientOnSessionUpdated; - _client.SessionApproved -= ClientOnSessionConnected; + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _client.SessionConnected -= ClientOnSessionConnected; + _client.SessionDeleted -= ClientOnSessionDeleted; + _client.SessionUpdateRequest -= ClientOnSessionUpdated; + _client.SessionApproved -= ClientOnSessionConnected; + + _client = null; + Sessions = null; + DefaultNamespace = null; + DefaultSession = default; + } - _client = null; - Sessions = null; - DefaultNamespace = null; - DefaultSession = default; + _disposed = true; } } diff --git a/WalletConnectSharp.Sign/Interfaces/IAddressProvider.cs b/WalletConnectSharp.Sign/Interfaces/IAddressProvider.cs index f39d19b..adc4738 100644 --- a/WalletConnectSharp.Sign/Interfaces/IAddressProvider.cs +++ b/WalletConnectSharp.Sign/Interfaces/IAddressProvider.cs @@ -17,11 +17,14 @@ public interface IAddressProvider : IModule ISession Sessions { get; } - Caip25Address CurrentAddress(string @namespace = null, SessionStruct session = default); Task InitAsync(); + Task SetDefaultNamespaceAsync(string @namespace); + Task SetDefaultChainIdAsync(string chainId); - Caip25Address[] AllAddresses(string @namespace = null, SessionStruct session = default); + Caip25Address CurrentAddress(string chainId = null, SessionStruct session = default); + + IEnumerable AllAddresses(string @namespace = null, SessionStruct session = default); } diff --git a/WalletConnectSharp.Sign/Models/SessionStruct.cs b/WalletConnectSharp.Sign/Models/SessionStruct.cs index 48035f4..d92a29a 100644 --- a/WalletConnectSharp.Sign/Models/SessionStruct.cs +++ b/WalletConnectSharp.Sign/Models/SessionStruct.cs @@ -82,51 +82,77 @@ public string Key return Topic; } } - - public Caip25Address CurrentAddress(string @namespace) + + public Caip25Address CurrentAddress(string chainId) { - // double check - if (@namespace == null) - throw new ArgumentException("SessionStruct.CurrentAddress: @namespace is null"); - if (string.IsNullOrWhiteSpace(Topic)) - throw new ArgumentException("SessionStruct.CurrentAddress: Session is undefined"); - - var defaultNamespace = Namespaces[@namespace]; + ValidateChainIdAndTopic(chainId); + + var namespaceStr = chainId.Split(':')[0]; + if (!Namespaces.TryGetValue(namespaceStr, out var defaultNamespace)) + { + throw new InvalidOperationException( + $"SessionStruct.CurrentAddress: Given namespace {namespaceStr} is not available in the current session"); + } + if (defaultNamespace.Accounts.Length == 0) - throw new Exception( - $"SessionStruct.CurrentAddress: Given namespace {@namespace} has no connected addresses"); + throw new InvalidOperationException( + $"SessionStruct.CurrentAddress: Given namespace {namespaceStr} has no connected addresses"); - var fullAddress = defaultNamespace.Accounts[0]; - var addressParts = fullAddress.Split(":"); + var fullAddress = Array.Find(defaultNamespace.Accounts, addr => addr.StartsWith(chainId)); + if (fullAddress == default) + { + throw new InvalidOperationException( + $"SessionStruct.CurrentAddress: No address found for chain {chainId}"); + } + + var address = fullAddress.Split(":")[2]; + return new Caip25Address { Address = address, ChainId = chainId }; + } + + public IEnumerable AllAddresses(string @namespace) + { + ValidateNamespaceAndTopic(@namespace); + + var defaultNamespace = Namespaces[@namespace]; + return defaultNamespace.Accounts.Length == 0 + ? [] + : defaultNamespace.Accounts.Select(CreateCaip25Address); + } + public static Caip25Address CreateCaip25Address(string fullAddress) + { + var addressParts = fullAddress.Split(":"); var address = addressParts[2]; var chainId = string.Join(':', addressParts.Take(2)); - return new Caip25Address() - { - Address = address, - ChainId = chainId, - }; + return new Caip25Address { Address = address, ChainId = chainId }; } - - public Caip25Address[] AllAddresses(string @namespace) + + private void ValidateNamespaceAndTopic(string @namespace) { - // double check if (@namespace == null) - throw new ArgumentException("SessionStruct.AllAddresses: @namespace is null"); + { + throw new ArgumentException("@namespace is null"); + } + if (string.IsNullOrWhiteSpace(Topic)) - throw new ArgumentException("SessionStruct.AllAddresses: Session is undefined"); - - var defaultNamespace = Namespaces[@namespace]; + { + throw new ArgumentException("Session is undefined"); + } + } - if (defaultNamespace.Accounts.Length == 0) - return null; //The namespace {@namespace} has no addresses connected") + private void ValidateChainIdAndTopic(string chainId) + { + if (chainId == null) + { + throw new ArgumentException("chainId is null"); + } - return defaultNamespace.Accounts.Select(addr => new Caip25Address() + if (string.IsNullOrWhiteSpace(Topic)) { - Address = addr.Split(":")[2], ChainId = string.Join(":", addr.Split(":").Take(2)) - }).ToArray(); + throw new ArgumentException("Session is undefined"); + } } } }