From cd421213d71d728d7b842a51b4aa2eef49ecf07d Mon Sep 17 00:00:00 2001 From: oleksandr Date: Wed, 18 Oct 2023 17:02:59 +0300 Subject: [PATCH 1/7] Added XML comments for Web3 folder --- src/ChainSafe.Gaming.Gelato/GelatoClient.cs | 12 ++-- .../Web3/Core/Analytics/ApiAnalyticsClient.cs | 3 +- .../Analytics/ApiAnalyticsClientExtensions.cs | 12 ++-- .../Web3/Core/Analytics/IAnalyticsClient.cs | 7 ++ .../Core/Analytics/NoOpAnalyticsClient.cs | 2 +- .../NoOpAnalyticsClientExtensions.cs | 12 ++++ .../Web3/Core/Build/IWeb3ServiceCollection.cs | 6 ++ .../Web3/Core/Build/Web3BuildException.cs | 3 + .../Web3/Core/Build/Web3Builder.cs | 22 +++++-- .../Build/Web3ServiceCollectionExtensions.cs | 40 ++++++++++++ .../Web3/Core/Debug/AddressExtensions.cs | 16 ++++- .../Web3/Core/Debug/AssertionException.cs | 12 ---- .../Web3/Core/Debug/ObjectExtensions.cs | 10 ++- .../Web3/Core/Debug/Web3AssertionException.cs | 13 ++++ .../Web3/Core/Environment/IHttpClient.cs | 65 +++++++++++++++++-- .../Web3/Core/Evm/ChainRegistryProvider.cs | 2 +- .../Web3/Core/IChainConfig.cs | 23 ++++++- .../Web3/Core/ICompleteProjectConfig.cs | 3 + .../Web3/Core/IInitializableWeb3.cs | 9 +++ .../Web3/Core/ILifecycleParticipant.cs | 14 +++- .../Web3/Core/IProjectConfig.cs | 6 ++ 21 files changed, 245 insertions(+), 47 deletions(-) delete mode 100644 src/ChainSafe.Gaming/Web3/Core/Debug/AssertionException.cs create mode 100644 src/ChainSafe.Gaming/Web3/Core/Debug/Web3AssertionException.cs create mode 100644 src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs diff --git a/src/ChainSafe.Gaming.Gelato/GelatoClient.cs b/src/ChainSafe.Gaming.Gelato/GelatoClient.cs index 89b2cdafd..9fdea7a9b 100644 --- a/src/ChainSafe.Gaming.Gelato/GelatoClient.cs +++ b/src/ChainSafe.Gaming.Gelato/GelatoClient.cs @@ -32,14 +32,14 @@ public async Task Post(RelayCall relayCall, TReq _ => throw new Web3Exception("relayCall option not found") }; - return (await httpClient.Post(url, request)).EnsureResponse(); + return (await httpClient.Post(url, request)).AssertSuccess(); } public async Task GetSupportedNetworks() { try { - return (await httpClient.Get($"{config.Url}/relays/v2")).EnsureResponse().Relays; + return (await httpClient.Get($"{config.Url}/relays/v2")).AssertSuccess().Relays; } catch (Exception e) { @@ -51,7 +51,7 @@ public async Task GetGelatoOracles() { try { - return (await httpClient.Get($"{config.Url}/oracles/")).EnsureResponse().Oracles; + return (await httpClient.Get($"{config.Url}/oracles/")).AssertSuccess().Oracles; } catch (Exception e) { @@ -63,7 +63,7 @@ public async Task GetPaymentTokens(string chainId) { try { - return (await httpClient.Get($"{config.Url}/oracles/${chainId}/paymentTokens/")).EnsureResponse().PaymentTokens; + return (await httpClient.Get($"{config.Url}/oracles/${chainId}/paymentTokens/")).AssertSuccess().PaymentTokens; } catch (Exception e) { @@ -75,7 +75,7 @@ public async Task GetEstimatedFeeRequest(EstimatedFeeRequest requ { try { - return (await httpClient.Post($"{config.Url}/oracles/${request.ChainId}/estimate/", request)).EnsureResponse().EstimatedFee; + return (await httpClient.Post($"{config.Url}/oracles/${request.ChainId}/estimate/", request)).AssertSuccess().EstimatedFee; } catch (Exception e) { @@ -87,7 +87,7 @@ public async Task GetTaskStatus(string taskId) { try { - return (await httpClient.Get($"{config.Url}/tasks/status/{taskId}")).EnsureResponse().Task; + return (await httpClient.Get($"{config.Url}/tasks/status/{taskId}")).AssertSuccess().Task; } catch (Exception e) { diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClient.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClient.cs index 7c96052bc..518aa86df 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClient.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClient.cs @@ -1,10 +1,9 @@ -using ChainSafe.Gaming.Web3.Core; using ChainSafe.Gaming.Web3.Environment; using Newtonsoft.Json; namespace ChainSafe.Gaming.Web3.Analytics { - public class ApiAnalyticsClient : IAnalyticsClient + internal class ApiAnalyticsClient : IAnalyticsClient { private const string LoggingUrl = "https://api.gaming.chainsafe.io/logging/logEvent"; private const string AnalyticsVersion = "2.5"; diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClientExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClientExtensions.cs index 0fa8458bb..1b528b084 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClientExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/ApiAnalyticsClientExtensions.cs @@ -1,4 +1,3 @@ -using System.Linq; using ChainSafe.Gaming.Web3.Build; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -7,6 +6,10 @@ namespace ChainSafe.Gaming.Web3.Analytics { public static class ApiAnalyticsClientExtensions { + /// + /// Binds thereby enabling analytics. + /// + /// Service collection to enable fluent syntax. public static IWeb3ServiceCollection UseApiAnalytics(this IWeb3ServiceCollection serviceCollection) { if (serviceCollection.AnalyticsDisabled()) @@ -17,12 +20,5 @@ public static IWeb3ServiceCollection UseApiAnalytics(this IWeb3ServiceCollection serviceCollection.Replace(ServiceDescriptor.Singleton()); return serviceCollection; } - - public static bool AnalyticsDisabled(this IWeb3ServiceCollection serviceCollection) - { - return serviceCollection.Any(d => - d.ServiceType == typeof(IAnalyticsClient) - && d.ImplementationType == typeof(NoOpAnalyticsClient)); - } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/IAnalyticsClient.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/IAnalyticsClient.cs index bcf9c64af..fbb87ac71 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/IAnalyticsClient.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/IAnalyticsClient.cs @@ -1,7 +1,14 @@ namespace ChainSafe.Gaming.Web3.Analytics { + /// + /// Interface for the Analytics Client. + /// public interface IAnalyticsClient { + /// + /// Captures an analytics event. + /// + /// The analytics event data. void CaptureEvent(AnalyticsEvent eventData); } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClient.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClient.cs index 60cfb5741..e0d4f3372 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClient.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClient.cs @@ -1,6 +1,6 @@ namespace ChainSafe.Gaming.Web3.Analytics { - public class NoOpAnalyticsClient : IAnalyticsClient + internal class NoOpAnalyticsClient : IAnalyticsClient { public void CaptureEvent(AnalyticsEvent eventData) { diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs index 6dc12fe62..e43495d2f 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs @@ -1,3 +1,4 @@ +using System.Linq; using ChainSafe.Gaming.Web3.Build; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -6,10 +7,21 @@ namespace ChainSafe.Gaming.Web3.Analytics { public static class NoOpAnalyticsClientExtensions { + /// + /// Disables analytics for the instance. + /// + /// Service collection to enable fluent syntax. public static IWeb3ServiceCollection DisableAnalytics(this IWeb3ServiceCollection serviceCollection) { serviceCollection.Replace(ServiceDescriptor.Singleton()); return serviceCollection; } + + public static bool AnalyticsDisabled(this IWeb3ServiceCollection serviceCollection) + { + return serviceCollection.Any(d => + d.ServiceType == typeof(IAnalyticsClient) + && d.ImplementationType == typeof(NoOpAnalyticsClient)); + } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/IWeb3ServiceCollection.cs b/src/ChainSafe.Gaming/Web3/Core/Build/IWeb3ServiceCollection.cs index b5197a492..55b8b1cc8 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/IWeb3ServiceCollection.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/IWeb3ServiceCollection.cs @@ -2,10 +2,16 @@ namespace ChainSafe.Gaming.Web3.Build { + /// + /// Collection of services to register in the Web3 dependency injection system. + /// public interface IWeb3ServiceCollection : IServiceCollection { } + /// + /// Collection of services to register in the Web3 dependency injection system. + /// public class Web3ServiceCollection : ServiceCollection, IWeb3ServiceCollection { } diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3BuildException.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3BuildException.cs index f42ba8c4b..99252e97f 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3BuildException.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3BuildException.cs @@ -3,6 +3,9 @@ namespace ChainSafe.Gaming.Web3.Build { + /// + /// Exception that indicates an error during build process. + /// public class Web3BuildException : Web3Exception { public Web3BuildException(string message) diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs index 372dccae8..957d705c5 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs @@ -10,13 +10,13 @@ namespace ChainSafe.Gaming.Web3.Build { /// - /// Builder object for Web3. Used to configure set of services. + /// Builder object for . Used to configure the set of services and other settings. /// public class Web3Builder { private readonly Web3ServiceCollection serviceCollection; - public Web3Builder() + private Web3Builder() { serviceCollection = new Web3ServiceCollection(); @@ -27,7 +27,6 @@ public Web3Builder() .AddSingleton(); } - // TODO: inline parameterless constructor into this one (therefore remove that overload) public Web3Builder(IProjectConfig projectConfig, IChainConfig chainConfig) : this() { @@ -50,8 +49,16 @@ public Web3Builder(ICompleteProjectConfig projectConfig) { } + /// + /// Delegate used to configure services for . + /// public delegate void ConfigureServicesDelegate(IWeb3ServiceCollection services); + /// + /// Configure services for . + /// + /// Delegate used to configure services for . + /// Builder object to enable fluent syntax. public Web3Builder Configure(ConfigureServicesDelegate configureMethod) { if (configureMethod is null) @@ -63,6 +70,10 @@ public Web3Builder Configure(ConfigureServicesDelegate configureMethod) return this; } + /// + /// Build object using the settings provided by this Web3Builder object. + /// + /// object. public async ValueTask BuildAsync() { var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -70,7 +81,8 @@ public async ValueTask BuildAsync() var web3 = new Web3(serviceProvider); - await web3.InitializeAsync(); + var initializableWeb3 = (IInitializableWeb3)web3; + await initializableWeb3.InitializeAsync(); return web3; } @@ -86,7 +98,7 @@ private static void AssertWeb3EnvironmentBound(IServiceProvider serviceProvider) { var message = $"{nameof(Web3Environment)} is required for Web3 to work." + "Don't forget to bind it when building Web3."; - throw new Web3Exception(message, e); + throw new Web3BuildException(message, e); } } } diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs index c5ed647bd..24cfb7961 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs @@ -6,6 +6,11 @@ namespace ChainSafe.Gaming.Web3.Build { public static class Web3ServiceCollectionExtensions { + /// + /// Assert that service of the specified type was not yet registered. + /// + /// Type of the service. + /// Service of the specified type was already bound. public static void AssertServiceNotBound(this IWeb3ServiceCollection services) { var assertType = typeof(T); @@ -16,6 +21,11 @@ public static void AssertServiceNotBound(this IWeb3ServiceCollection services } } + /// + /// Assert that configuration object of the specified type was not yet registered. + /// + /// Type of the configuration object. + /// Configuration object of the specified type was already bound. public static void AssertConfigurationNotBound(this IWeb3ServiceCollection services) { var assertType = typeof(T); @@ -26,6 +36,12 @@ public static void AssertConfigurationNotBound(this IWeb3ServiceCollection se } } + /// + /// Register the specified implementation using 2 contract types. + /// + /// First contract type. + /// Second contract type. + /// Implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class @@ -43,6 +59,14 @@ public static void AddSingleton(this serviceCollection.AddSingleton(sp => sp.GetRequiredService()); } + /// + /// Register the specified implementation for 2 contract types using the factory method. + /// + /// Service collection. + /// Factory method. + /// First contract type. + /// Second contract type. + /// Implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class @@ -53,6 +77,13 @@ public static void AddSingleton(this serviceCollection.AddSingleton(sp => sp.GetRequiredService()); } + /// + /// Register the specified implementation using 3 contract types. + /// + /// First contract type. + /// Second contract type. + /// Third contract type. + /// Implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class @@ -65,6 +96,15 @@ public static void AddSingleton(sp => sp.GetRequiredService()); } + /// + /// Register the specified implementation for 3 contract types using the factory method. + /// + /// Service collection. + /// Factory method. + /// First contract type. + /// Second contract type. + /// Third contract type. + /// Implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class diff --git a/src/ChainSafe.Gaming/Web3/Core/Debug/AddressExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Debug/AddressExtensions.cs index 01a5843c5..eec817bee 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Debug/AddressExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Debug/AddressExtensions.cs @@ -1,20 +1,30 @@ -using ChainSafe.Gaming.Web3.Core; - namespace ChainSafe.Gaming.Web3.Core.Debug { public static class AddressExtensions { + /// + /// Check if the string provided is a public address. + /// + /// String to check. + /// True if the string provided is a public address. public static bool IsPublicAddress(string value) { // TODO: more accurate test/Regex return !string.IsNullOrEmpty(value) && value.Length == 42; } + /// + /// Assert that the string provided is a public address. + /// + /// String to check. + /// Name of the string variable (nameof). + /// String that was checked. + /// The string provided is not public address. public static string AssertIsPublicAddress(this string value, string variableName) { if (!IsPublicAddress(value)) { - throw new Web3Exception($"\"{variableName}\" is not public address"); + throw new Web3AssertionException($"\"{variableName}\" is not public address"); } return value; diff --git a/src/ChainSafe.Gaming/Web3/Core/Debug/AssertionException.cs b/src/ChainSafe.Gaming/Web3/Core/Debug/AssertionException.cs deleted file mode 100644 index 7d08f296e..000000000 --- a/src/ChainSafe.Gaming/Web3/Core/Debug/AssertionException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace ChainSafe.Gaming.Web3.Core.Debug -{ - public class AssertionException : Exception - { - public AssertionException(string message) - : base(message) - { - } - } -} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Debug/ObjectExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Debug/ObjectExtensions.cs index a5fde8578..3c2fcb1b2 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Debug/ObjectExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Debug/ObjectExtensions.cs @@ -3,12 +3,20 @@ namespace ChainSafe.Gaming.Web3.Core.Debug public static class ObjectExtensions { #nullable enable + /// + /// Asserts that the object provided is not null. + /// + /// Object to check. + /// Name of the variable to check (nameof). + /// Type of the variable to check. + /// The object provided. + /// The provided object is null. public static T AssertNotNull(this T? obj, string variableName) where T : notnull { if (obj is null) { - throw new AssertionException($"{variableName} is null."); + throw new Web3AssertionException($"{variableName} is null."); } return obj; diff --git a/src/ChainSafe.Gaming/Web3/Core/Debug/Web3AssertionException.cs b/src/ChainSafe.Gaming/Web3/Core/Debug/Web3AssertionException.cs new file mode 100644 index 000000000..118471023 --- /dev/null +++ b/src/ChainSafe.Gaming/Web3/Core/Debug/Web3AssertionException.cs @@ -0,0 +1,13 @@ +namespace ChainSafe.Gaming.Web3.Core.Debug +{ + /// + /// Exception indicating that an assertion check failed. + /// + public class Web3AssertionException : Web3Exception + { + public Web3AssertionException(string message) + : base(message) + { + } + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Environment/IHttpClient.cs b/src/ChainSafe.Gaming/Web3/Core/Environment/IHttpClient.cs index 628c9c532..f596d5fa9 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Environment/IHttpClient.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Environment/IHttpClient.cs @@ -3,46 +3,99 @@ namespace ChainSafe.Gaming.Web3.Environment { + /// + /// Interface for HTTP Client to be used by the SDK. + /// public interface IHttpClient { + /// + /// Makes a GET request. + /// + /// URL to send request to. + /// Server response. ValueTask> GetRaw(string url); + /// + /// Makes a POST request. + /// + /// URL to send request to. + /// Data to send. + /// Content type of the data (ex. 'application/json'). + /// Server response. ValueTask> PostRaw(string url, string data, string contentType); + /// + /// Makes a GET request. Deserializes response from JSON to the specified type. + /// + /// URL to send request to. + /// Type of the response data. + /// Server response. ValueTask> Get(string url); + /// + /// Makes a POST request. Handles JSON serialization/deserialization of request and response for the specified types. + /// + /// URL to send request to. + /// Data object to send. + /// Type of content used for request. + /// Type of content expected as the response. + /// Server response. ValueTask> Post(string url, TRequest data); } + /// + /// Represents server response. + /// + /// Type of content expected as the response. public class NetworkResponse { + /// + /// Response body. + /// public T Response { get; private set; } + /// + /// Request error. + /// public string Error { get; private set; } + /// + /// Was the request successful. + /// public bool IsSuccess { get; private set; } + /// + /// Shorthand to create a new instance of response for a successful request. + /// + /// Response body. + /// New instance of . public static NetworkResponse Success(T response) { return new() { Response = response, IsSuccess = true }; } + /// + /// Shorthand to create a new instance of response for a failed request. + /// + /// Error message. + /// New instance of . public static NetworkResponse Failure(string error) { return new() { Error = error, IsSuccess = false }; } - public void EnsureSuccess() + /// + /// Assert that the request was successful. + /// + /// Response object to enable fluent syntax. + /// Request was not successful. + public T AssertSuccess() { if (!IsSuccess) { - throw new Exception(Error); + throw new Web3Exception(Error); } - } - public T EnsureResponse() - { - EnsureSuccess(); return Response; } diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs index d91e65c7b..d8d870972 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs @@ -29,7 +29,7 @@ public ChainRegistryProvider(Web3Environment environment) { var httpClient = environment.HttpClient; var response = await httpClient.Get(FetchUrl); - return response.EnsureResponse().ToDictionary(chain => chain.ChainId, chain => chain); + return response.AssertSuccess().ToDictionary(chain => chain.ChainId, chain => chain); } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/IChainConfig.cs b/src/ChainSafe.Gaming/Web3/Core/IChainConfig.cs index 7d08b4e73..708f7d982 100644 --- a/src/ChainSafe.Gaming/Web3/Core/IChainConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/IChainConfig.cs @@ -1,17 +1,38 @@ namespace ChainSafe.Gaming.Web3 { - public interface IChainConfig + /// + /// Configuration object containing chain settings. + /// + public interface IChainConfig // TODO: double check these xml docs pls { + /// + /// The id of the chain to be used. Equals '1' for Ethereum Mainnet. + /// public string ChainId { get; } + /// + /// The name of the chain to be used. Equals 'Ethereum' for Ethereum Mainnet. + /// public string Chain { get; } + /// + /// The name of the network to be used. Equals 'Ethereum Mainnet' for Ethereum Mainnet. + /// public string Network { get; } + /// + /// The URI for the RPC endpoint to be used by the RPC provider by default. + /// public string Rpc { get; } + /// + /// The path to the IPC file to be used by the IPC provider by default. + /// public string Ipc { get; } + /// + /// TODO. + /// public string Ws { get; } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/ICompleteProjectConfig.cs b/src/ChainSafe.Gaming/Web3/Core/ICompleteProjectConfig.cs index 1302dd001..e94f74bb3 100644 --- a/src/ChainSafe.Gaming/Web3/Core/ICompleteProjectConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/ICompleteProjectConfig.cs @@ -1,5 +1,8 @@ namespace ChainSafe.Gaming.Web3 { + /// + /// merged with . + /// public interface ICompleteProjectConfig : IProjectConfig, IChainConfig { } diff --git a/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs b/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs new file mode 100644 index 000000000..16cb54bf2 --- /dev/null +++ b/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace ChainSafe.Gaming.Web3.Core +{ + internal interface IInitializableWeb3 + { + ValueTask InitializeAsync(); + } +} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/ILifecycleParticipant.cs b/src/ChainSafe.Gaming/Web3/Core/ILifecycleParticipant.cs index 65d0e1f80..347a0a907 100644 --- a/src/ChainSafe.Gaming/Web3/Core/ILifecycleParticipant.cs +++ b/src/ChainSafe.Gaming/Web3/Core/ILifecycleParticipant.cs @@ -5,10 +5,22 @@ namespace ChainSafe.Gaming.Web3.Core { - public interface ILifecycleParticipant + /// + /// Services and components that implement this interface will receive callbacks on + /// initialization and termination. + /// + public interface ILifecycleParticipant // TODO: split this into two separate interfaces? { + /// + /// Called on initialization. + /// + /// Task handle for the asynchronous process. ValueTask WillStartAsync(); + /// + /// Called on termination. + /// + /// Task handle for the asynchronous process. ValueTask WillStopAsync(); } } diff --git a/src/ChainSafe.Gaming/Web3/Core/IProjectConfig.cs b/src/ChainSafe.Gaming/Web3/Core/IProjectConfig.cs index a79d0878f..cd23b6799 100644 --- a/src/ChainSafe.Gaming/Web3/Core/IProjectConfig.cs +++ b/src/ChainSafe.Gaming/Web3/Core/IProjectConfig.cs @@ -1,7 +1,13 @@ namespace ChainSafe.Gaming.Web3 { + /// + /// Configuration object containing project settings. + /// public interface IProjectConfig { + /// + /// The project id issued by ChainSafe. Follow https://docs.gaming.chainsafe.io to learn more. + /// public string ProjectId { get; } } } \ No newline at end of file From 0ffd32cf66e0856ef4f18127372dce157ee50c57 Mon Sep 17 00:00:00 2001 From: oleksandr Date: Thu, 19 Oct 2023 12:46:00 +0300 Subject: [PATCH 2/7] Added XML comments for Web3 folder (2) --- src/ChainSafe.Gaming/Web3/Core/Web3.cs | 77 +++++++++++++------ .../Web3/Core/Web3Exception.cs | 3 + .../Web3/Evm/JsonRpc/RpcClientProvider.cs | 2 +- .../Scripts/Erc1155MetaDataReader.cs | 2 +- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/ChainSafe.Gaming/Web3/Core/Web3.cs b/src/ChainSafe.Gaming/Web3/Core/Web3.cs index c30104991..01df0be9a 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Web3.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Web3.cs @@ -12,8 +12,9 @@ namespace ChainSafe.Gaming.Web3 { /// /// Facade for all Web3-related services. + /// Use this as an entry point to all SDK features. /// - public class Web3 : IAsyncDisposable + public class Web3 : IAsyncDisposable, IInitializableWeb3 { private readonly ServiceProvider serviceProvider; private readonly IRpcProvider? rpcProvider; @@ -36,61 +37,69 @@ internal Web3(ServiceProvider serviceProvider) ChainConfig = serviceProvider.GetRequiredService(); } + /// + /// Access the component bound to the Web3 instance during the build phase. + /// public IRpcProvider RpcProvider => AssertComponentAccessible(rpcProvider, nameof(RpcProvider)); + /// + /// Access the component bound to the Web3 instance during the build phase. + /// public ISigner Signer => AssertComponentAccessible(signer, nameof(Signer)); + /// + /// Access the component bound to the Web3 instance during the build phase. + /// public ITransactionExecutor TransactionExecutor => AssertComponentAccessible(transactionExecutor, nameof(TransactionExecutor)); + /// + /// Access the event service of the Web3 instance. + /// public IEvmEvents Events => AssertComponentAccessible(events, nameof(Events)); + /// + /// Access the factory. + /// public IContractBuilder ContractBuilder { get; } + /// + /// Access the project configuration object. + /// public IProjectConfig ProjectConfig { get; } + /// + /// Access the chain configuration object. + /// public IChainConfig ChainConfig { get; } + /// + /// Access the service provider of this Web3 instance. + /// Use this to get any service, that was bound to this Web3 instance + /// during the build phase. + /// public IServiceProvider ServiceProvider => serviceProvider; - private static T AssertComponentAccessible(T? value, string propertyName) - where T : notnull - { - if (value == null) - { - throw new Web3Exception( - $"{propertyName} is not bound. Make sure to add an implementation of {propertyName} before using it."); - } - - // TODO: uncomment after migration complete - // if (!_initialized) - // { - // throw new Web3Exception($"Can't access {propertyName}. Initialize Web3 first."); - // } - return value; - } - async ValueTask IAsyncDisposable.DisposeAsync() { await TerminateAsync(); GC.SuppressFinalize(this); } - public async ValueTask InitializeAsync() + async ValueTask IInitializableWeb3.InitializeAsync() { - if (initialized) - { - throw new Web3Exception("Web3 was already initialized."); - } - foreach (var lifecycleParticipant in serviceProvider.GetServices()) { await lifecycleParticipant.WillStartAsync(); } - // TODO: initialize other components initialized = true; } + /// + /// Terminate this Web3 instance together with all of its components. + /// + /// Web3 was already terminated. + /// Task handle for the asynchronous process. public async ValueTask TerminateAsync() { if (terminated) @@ -109,5 +118,23 @@ public async ValueTask TerminateAsync() serviceProvider.Dispose(); terminated = true; } + + private T AssertComponentAccessible(T? value, string propertyName) + where T : notnull + { + if (value == null) + { + throw new Web3Exception( + $"{propertyName} is not bound. Make sure to add an implementation of {propertyName} before using it."); + } + + // TODO: uncomment after migration complete + if (!initialized) + { + throw new Web3Exception($"Can't access {propertyName}. Web3 instance should be initialized first."); + } + + return value; + } } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Web3Exception.cs b/src/ChainSafe.Gaming/Web3/Core/Web3Exception.cs index 68ef3f953..033c607b3 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Web3Exception.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Web3Exception.cs @@ -2,6 +2,9 @@ namespace ChainSafe.Gaming.Web3 { + /// + /// Web3-related exception. + /// public class Web3Exception : Exception { public Web3Exception(string message) diff --git a/src/ChainSafe.Gaming/Web3/Evm/JsonRpc/RpcClientProvider.cs b/src/ChainSafe.Gaming/Web3/Evm/JsonRpc/RpcClientProvider.cs index 5748ab398..5e57b3776 100644 --- a/src/ChainSafe.Gaming/Web3/Evm/JsonRpc/RpcClientProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Evm/JsonRpc/RpcClientProvider.cs @@ -104,7 +104,7 @@ public async Task Perform(string method, params object[] parameters) var request = new RpcRequestMessage(Guid.NewGuid().ToString(), method, parameters); var response = (await httpClient.Post(config.RpcNodeUrl, request)) - .EnsureResponse(); + .AssertSuccess(); if (response.HasError) { diff --git a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/LootBoxes/Scripts/Erc1155MetaDataReader.cs b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/LootBoxes/Scripts/Erc1155MetaDataReader.cs index d11dd6907..25fc725ec 100644 --- a/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/LootBoxes/Scripts/Erc1155MetaDataReader.cs +++ b/src/UnitySampleProject/Assets/Samples/web3.unity SDK/2.5.0/LootBoxes/Scripts/Erc1155MetaDataReader.cs @@ -41,7 +41,7 @@ public async Task Fetch(string uri, BigInteger tokenId) var response = await httpClient.Get(uri); - return response.EnsureResponse(); + return response.AssertSuccess(); } private Erc1155MetaData DecodeUri(string uri) From 1ac143033d77466df9f7776e919e8598a7280b93 Mon Sep 17 00:00:00 2001 From: oleksandr Date: Thu, 19 Oct 2023 18:33:06 +0300 Subject: [PATCH 3/7] Added XML comments for Web3 folder (3) --- .../Web3/Core/Evm/ChainRegistryProvider.cs | 17 +- .../Web3/Core/Evm/IEvmEvents.cs | 29 +++ .../Web3/Core/Evm/IRpcProvider.cs | 30 ++- src/ChainSafe.Gaming/Web3/Core/Evm/ISigner.cs | 33 +++ .../Web3/Core/Evm/ITransactionExecutor.cs | 15 ++ .../Web3/Core/Evm/RpcProviderExtensions.cs | 201 ++++++++++++++++-- src/ChainSafe.Gaming/Web3/Core/Web3.cs | 17 +- 7 files changed, 314 insertions(+), 28 deletions(-) diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs index d8d870972..72d4d8c91 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs @@ -7,18 +7,28 @@ namespace ChainSafe.Gaming.Evm { + /// + /// Provides access to a registry of chain info by their chain IDs. + /// public class ChainRegistryProvider { private const string FetchUrl = "https://chainid.network/chains.json"; - private readonly Web3Environment environment; + private readonly IHttpClient httpClient; + private Dictionary? chains; - public ChainRegistryProvider(Web3Environment environment) + internal ChainRegistryProvider(IHttpClient httpClient) { - this.environment = environment; + this.httpClient = httpClient; } + /// + /// Asynchronously retrieves a blockchain chain by its chain ID. + /// + /// The chain ID to retrieve. + /// Requested chain info. + // TODO: refactor to load all chains on WillStartAsync, make this method sync public async ValueTask GetChain(ulong chainId) { chains ??= await LoadAllChains(); @@ -27,7 +37,6 @@ public ChainRegistryProvider(Web3Environment environment) private async ValueTask> LoadAllChains() { - var httpClient = environment.HttpClient; var response = await httpClient.Get(FetchUrl); return response.AssertSuccess().ToDictionary(chain => chain.ChainId, chain => chain); } diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/IEvmEvents.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/IEvmEvents.cs index 686dc0632..10174b643 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/IEvmEvents.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/IEvmEvents.cs @@ -6,20 +6,49 @@ namespace ChainSafe.Gaming.Web3.Core.Evm { public interface IEvmEvents { + /// + /// Represents a delegate for handling chain change events. + /// + /// The chain ID of the new chain. public delegate void ChainChangedDelegate(ulong chainID); + /// + /// Represents a delegate for handling poll error events. + /// + /// The exception representing the poll error. public delegate void PollErrorDelegate(Exception exception); + /// + /// Represents a delegate for handling poll events. + /// + /// The ID of the poll event. + /// The block number associated with the poll event. public delegate void PollDelegate(ulong pollID, ulong blockNumber); + /// + /// Represents a delegate for handling new block events. + /// + /// The block number of the new block. public delegate void NewBlockDelegate(ulong blockNumber); + /// + /// Occurs when the chain is changed. + /// public event ChainChangedDelegate ChainChanged; + /// + /// Occurs when an error is encountered during polling. + /// public event PollErrorDelegate PollError; + /// + /// Occurs when a poll event is triggered. + /// public event PollDelegate Poll; + /// + /// Occurs when a new block is detected. + /// public event NewBlockDelegate NewBlock; } } diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/IRpcProvider.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/IRpcProvider.cs index f530d3d8b..7064311e2 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/IRpcProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/IRpcProvider.cs @@ -2,14 +2,40 @@ namespace ChainSafe.Gaming.Evm.Providers { + /// + /// Represents an interface for an RPC (Remote Procedure Call) provider in a blockchain environment. + /// + /// + /// RPC provider is a core component that allows to communicate with + /// a blockchain network using remote procedure calls, + /// enabling actions such as querying blockchain data. + /// public interface IRpcProvider { + /// + /// Gets the last known blockchain network information. + /// Network.Network LastKnownNetwork { get; } - // Network + /// + /// Asynchronously refreshes and retrieves the current blockchain network information. + /// + /// + /// A representing the asynchronous operation. The task result contains + /// the updated object representing the current network. + /// Task RefreshNetwork(); - // ENS + /// + /// Asynchronously performs a specific RPC method on the blockchain. + /// + /// The expected return type of the RPC method. + /// The name of the RPC method to execute. + /// An array of parameters to pass to the RPC method. + /// + /// A representing the asynchronous operation. The task result contains + /// the result of the RPC method, deserialized to the specified return type . + /// Task Perform(string method, params object[] parameters); } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/ISigner.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/ISigner.cs index 5dfd59bd9..aa50308d4 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/ISigner.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/ISigner.cs @@ -3,12 +3,45 @@ namespace ChainSafe.Gaming.Evm.Signers { + /// + /// Represents a component responsible for signing transactions, messages, and providing the player's public address. + /// + /// + /// Signer serves as a secure and essential element that encapsulates a user's + /// private key, enabling the signing of messages and transactions. Additionally, it provides + /// the user's public address for identity verification on the blockchain network. + /// public interface ISigner { + /// + /// Asynchronously retrieves the wallet address associated with the signer. + /// + /// + /// A representing the asynchronous operation. The task result contains + /// the wallet address associated with the signer as a string. + /// Task GetAddress(); + /// + /// Asynchronously signs a given message. + /// + /// The message to sign as a string. + /// + /// A representing the asynchronous operation. The task result contains + /// the signature of the message as a string. + /// Task SignMessage(string message); + /// + /// Asynchronously signs a structured message using the provided domain parameters. + /// + /// The type of the structured message to sign. + /// The domain parameters for signing. + /// The structured message to sign. + /// + /// A representing the asynchronous operation. The task result contains + /// the signature of the structured message as a string. + /// Task SignTypedData(SerializableDomain domain, TStructType message); // TODO: is this the right thing to do? diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/ITransactionExecutor.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/ITransactionExecutor.cs index 7903ebbc9..da1ef8ad5 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/ITransactionExecutor.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/ITransactionExecutor.cs @@ -3,8 +3,23 @@ namespace ChainSafe.Gaming.Web3.Core.Evm { + /// + /// Represents an interface for executing blockchain transactions. + /// + /// + /// TransactionExecutor is a core component responsible for the seamless transmission of transactions to the + /// blockchain network for execution. + /// public interface ITransactionExecutor { + /// + /// Asynchronously sends a transaction to the blockchain network. + /// + /// The transaction request to be sent. + /// + /// A representing the asynchronous operation. The task result contains + /// a object with details about the executed transaction. + /// public Task SendTransaction(TransactionRequest transaction); } } \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs index 319076029..b4b82dabc 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/RpcProviderExtensions.cs @@ -18,6 +18,16 @@ namespace ChainSafe.Gaming.Evm.Providers { public static class RpcProviderExtensions { + /// + /// eth_getBalance
Asynchronously retrieves the native balance (ETH for Ethereum) of a specified wallet address. + ///
+ /// The RPC provider. + /// The wallet address to query. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the native balance as a . + /// public static async Task GetBalance(this IRpcProvider provider, string address, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); @@ -27,6 +37,16 @@ public static async Task GetBalance(this IRpcProvider provider, s return new HexBigInteger(await provider.Perform("eth_getBalance", parameters)); } + /// + /// eth_getCode
Asynchronously retrieves the byte code of a smart contract at a specified address. + ///
+ /// The RPC provider. + /// The smart contract address to query. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the byte code as a hexadecimal string. + /// public static async Task GetCode(this IRpcProvider provider, string address, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); @@ -36,6 +56,17 @@ public static async Task GetCode(this IRpcProvider provider, string addr return await provider.Perform("eth_getCode", parameters); } + /// + /// eth_getStorageAt
Asynchronously retrieves the storage data at a specified address and position. + ///
+ /// The RPC provider. + /// The address to query. + /// The storage position to query. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the storage data as a string. + /// public static async Task GetStorageAt(this IRpcProvider provider, string address, BigInteger position, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); @@ -45,6 +76,16 @@ public static async Task GetStorageAt(this IRpcProvider provider, string return await provider.Perform("eth_getStorageAt", parameters); } + /// + /// eth_getTransactionCount
Asynchronously retrieves the transaction count for a specified address. + ///
+ /// The RPC provider. + /// The address to query. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the transaction count as a . + /// public static async Task GetTransactionCount(this IRpcProvider provider, string address, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); @@ -54,16 +95,34 @@ public static async Task GetTransactionCount(this IRpcProvider pr return new HexBigInteger(await provider.Perform("eth_getTransactionCount", parameters)); } - public static async Task GetBlock(this IRpcProvider provider, BlockParameter blockTag = null) + /// + /// eth_getBlockByNumber
Asynchronously retrieves a blockchain block. + ///
+ /// The RPC provider. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the blockchain block as a . + /// + public static async Task GetBlock(this IRpcProvider provider, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); var parameters = new object[] { blockTag.GetRPCParam(), false }; - return await provider.Perform("eth_getBlockByNumber", parameters); + return await provider.Perform("eth_getBlockByNumber", parameters); } - public static async Task GetBlock(this IRpcProvider provider, string blockHash) + /// + /// eth_getBlockByHash
Asynchronously retrieves a blockchain block using its hash. + ///
+ /// The RPC provider. + /// The hash of the block to retrieve. + /// + /// A representing the asynchronous operation. + /// The task result contains the blockchain block as a . + /// + public static async Task GetBlock(this IRpcProvider provider, string blockHash) { if (!blockHash.HasHexPrefix() || blockHash.Length != 66) { @@ -72,19 +131,37 @@ public static async Task GetTransactionCount(this IRpcProvider pr var parameters = new object[] { blockHash, false }; - return await provider.Perform("eth_getBlockByHash", parameters); + return await provider.Perform("eth_getBlockByHash", parameters); } - public static async Task GetBlockWithTransactions(this IRpcProvider provider, BlockParameter blockTag = null) + /// + /// eth_getBlockByNumber
Asynchronously retrieves a blockchain block with its transactions. + ///
+ /// The RPC provider. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the blockchain block with transactions as a . + /// + public static async Task GetBlockWithTransactions(this IRpcProvider provider, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); var parameters = new object[] { blockTag.GetRPCParam(), true }; - return await provider.Perform("eth_getBlockByNumber", parameters); + return await provider.Perform("eth_getBlockByNumber", parameters); } - public static async Task GetBlockWithTransactions(this IRpcProvider provider, string blockHash) + /// + /// eth_getBlockByHash
Asynchronously retrieves a blockchain block with its transactions using the block's hash. + ///
+ /// The RPC provider. + /// The hash of the block to retrieve. + /// + /// A representing the asynchronous operation. + /// The task result contains the blockchain block with transactions as a . + /// + public static async Task GetBlockWithTransactions(this IRpcProvider provider, string blockHash) { if (!blockHash.HasHexPrefix() || blockHash.Length != 66) { @@ -93,19 +170,43 @@ public static async Task GetTransactionCount(this IRpcProvider pr var parameters = new object[] { blockHash, true }; - return await provider.Perform("eth_getBlockByHash", parameters); + return await provider.Perform("eth_getBlockByHash", parameters); } + /// + /// eth_blockNumber
Asynchronously retrieves the latest block number on the blockchain. + ///
+ /// The RPC provider. + /// + /// A representing the asynchronous operation. + /// The task result contains the latest block number as a . + /// public static async Task GetBlockNumber(this IRpcProvider provider) { return new HexBigInteger(await provider.Perform("eth_blockNumber", null)); } + /// + /// eth_gasPrice
Asynchronously retrieves the current gas price on the blockchain. + ///
+ /// The RPC provider. + /// + /// A representing the asynchronous operation. + /// The task result contains the current gas price as a . + /// public static async Task GetGasPrice(this IRpcProvider provider) { return new HexBigInteger(await provider.Perform("eth_gasPrice", null)); } + /// + /// Asynchronously retrieves fee-related data for transactions. + /// + /// The RPC provider. + /// + /// A representing the asynchronous operation. + /// The task result contains fee data as a object. + /// public static async Task GetFeeData(this IRpcProvider provider) { var block = await provider.GetBlock(); @@ -149,6 +250,16 @@ async Task TryFetchMaxFees() } } + /// + /// eth_call
Asynchronously invokes a call to a smart contract or blockchain function. + ///
+ /// The RPC provider. + /// The transaction request to execute. + /// The block parameter (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the result of the call as a string. + /// public static async Task Call(this IRpcProvider provider, TransactionRequest transaction, BlockParameter blockTag = null) { blockTag ??= new BlockParameter(); @@ -158,6 +269,15 @@ public static async Task Call(this IRpcProvider provider, TransactionReq return await provider.Perform("eth_call", parameters); } + /// + /// eth_estimateGas
Asynchronously estimates the gas required for a transaction. + ///
+ /// The RPC provider. + /// The transaction request to estimate gas for. + /// + /// A representing the asynchronous operation. + /// The task result contains the estimated gas amount as a . + /// public static async Task EstimateGas(this IRpcProvider provider, TransactionRequest transaction) { var parameters = new object[] { transaction }; @@ -165,6 +285,15 @@ public static async Task EstimateGas(this IRpcProvider provider, return new HexBigInteger(await provider.Perform("eth_estimateGas", parameters)); } + /// + /// eth_getTransactionByHash
Asynchronously retrieves a transaction by its hash. + ///
+ /// The RPC provider. + /// The hash of the transaction to retrieve. + /// + /// A representing the asynchronous operation. + /// The task result contains the transaction details as a . + /// public static async Task GetTransaction(this IRpcProvider provider, string transactionHash) { var parameters = new object[] { transactionHash }; @@ -195,11 +324,20 @@ public static async Task GetTransaction(this IRpcProvider p return result; } - public static async Task GetTransactionReceipt(this IRpcProvider provider, string transactionHash) + /// + /// eth_getTransactionReceipt
Asynchronously retrieves a transaction receipt by its hash. + ///
+ /// The RPC provider. + /// The hash of the transaction receipt to retrieve. + /// + /// A representing the asynchronous operation. + /// The task result contains the transaction receipt as a . + /// + public static async Task GetTransactionReceipt(this IRpcProvider provider, string transactionHash) { var parameters = new object[] { transactionHash }; - var result = await provider.Perform("eth_getTransactionReceipt", parameters); + var result = await provider.Perform("eth_getTransactionReceipt", parameters); if (result == null) { @@ -226,7 +364,16 @@ public static async Task GetTransaction(this IRpcProvider p return result; } - public static TransactionResponse WrapTransaction(this IRpcProvider provider, Transactions.Transaction tx, string hash) + /// + /// Wraps a transaction with its hash to create a . + /// + /// The RPC provider. + /// The original transaction. + /// The hash of the transaction. + /// + /// A object with the transaction details. + /// + public static TransactionResponse WrapTransaction(this IRpcProvider provider, Transaction tx, string hash) { if (hash != null && hash.Length != 66) { @@ -239,7 +386,18 @@ public static TransactionResponse WrapTransaction(this IRpcProvider provider, Tr return result; } - public static async Task WaitForTransactionReceipt( + /// + /// Asynchronously waits for a transaction receipt with specified confirmations and optional timeout. + /// + /// The RPC provider. + /// The hash of the transaction receipt to wait for. + /// The number of confirmations to wait for (optional). + /// The maximum number of attempts before timing out (optional). + /// + /// A representing the asynchronous operation. + /// The task result contains the transaction receipt as a . + /// + public static async Task WaitForTransactionReceipt( this IRpcProvider provider, string transactionHash, uint confirmations = 1, @@ -248,7 +406,7 @@ public static TransactionResponse WrapTransaction(this IRpcProvider provider, Tr return await provider.WaitForTransactionInternal(transactionHash, confirmations, timeout); } - private static async Task WaitForTransactionInternal( + private static async Task WaitForTransactionInternal( this IRpcProvider provider, string transactionHash, uint confirmations = 1, @@ -288,6 +446,15 @@ public static TransactionResponse WrapTransaction(this IRpcProvider provider, Tr } } + /// + /// eth_getLogs
Asynchronously retrieves logs based on the provided filter criteria. + ///
+ /// The RPC provider. + /// The filter input criteria for log retrieval. + /// + /// A representing the asynchronous operation. + /// The task result contains an array of objects representing the logs. + /// public static async Task GetLogs(this IRpcProvider provider, NewFilterInput filter) { var parameters = new object[] { filter }; @@ -295,6 +462,14 @@ public static async Task GetLogs(this IRpcProvider provider, NewFil return await provider.Perform("eth_getLogs", parameters); } + /// + /// eth_accounts
Asynchronously lists all accounts associated with the RPC node. + ///
+ /// The RPC provider. + /// + /// A representing the asynchronous operation. + /// The task result contains an array of account addresses as strings. + /// public static async Task ListAccounts(this IRpcProvider provider) => await provider.Perform("eth_accounts"); } diff --git a/src/ChainSafe.Gaming/Web3/Core/Web3.cs b/src/ChainSafe.Gaming/Web3/Core/Web3.cs index 01df0be9a..85b90895e 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Web3.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Web3.cs @@ -38,44 +38,43 @@ internal Web3(ServiceProvider serviceProvider) } /// - /// Access the component bound to the Web3 instance during the build phase. + /// Access the component, which provides RPC communication with the Ethereum network. /// public IRpcProvider RpcProvider => AssertComponentAccessible(rpcProvider, nameof(RpcProvider)); /// - /// Access the component bound to the Web3 instance during the build phase. + /// Access the component, responsible for signing transactions, messages, and providing the player's public address. /// public ISigner Signer => AssertComponentAccessible(signer, nameof(Signer)); /// - /// Access the component bound to the Web3 instance during the build phase. + /// Access the component, used for sending transactions to the blockchain. /// public ITransactionExecutor TransactionExecutor => AssertComponentAccessible(transactionExecutor, nameof(TransactionExecutor)); /// - /// Access the event service of the Web3 instance. + /// Access the event service of the Web3 instance, allowing you to subscribe to blockchain events. /// public IEvmEvents Events => AssertComponentAccessible(events, nameof(Events)); /// - /// Access the factory. + /// Access the factory for creating Ethereum smart contract wrappers. /// public IContractBuilder ContractBuilder { get; } /// - /// Access the project configuration object. + /// Access the project configuration object, providing access to project-specific settings. /// public IProjectConfig ProjectConfig { get; } /// - /// Access the chain configuration object. + /// Access the chain configuration object, providing access to blockchain-specific settings. /// public IChainConfig ChainConfig { get; } /// /// Access the service provider of this Web3 instance. - /// Use this to get any service, that was bound to this Web3 instance - /// during the build phase. + /// Use this to retrieve any service that was bound to this Web3 instance during the build phase. /// public IServiceProvider ServiceProvider => serviceProvider; From 63fa97290fffe3aaf0f81f554cd37e5ffa6eb4bc Mon Sep 17 00:00:00 2001 From: oleksandr Date: Fri, 20 Oct 2023 13:41:14 +0300 Subject: [PATCH 4/7] Fixed ChainRegistryProvider constructor --- src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs index 72d4d8c91..be72eb950 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Evm/ChainRegistryProvider.cs @@ -18,7 +18,7 @@ public class ChainRegistryProvider private Dictionary? chains; - internal ChainRegistryProvider(IHttpClient httpClient) + public ChainRegistryProvider(IHttpClient httpClient) { this.httpClient = httpClient; } From 6e96b653a9a081bfd3b3712711ba160e311cb725 Mon Sep 17 00:00:00 2001 From: oleksandr Date: Mon, 23 Oct 2023 14:49:25 +0300 Subject: [PATCH 5/7] Removed IInitializableWeb3 --- src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs | 4 +--- src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs | 9 --------- src/ChainSafe.Gaming/Web3/Core/Web3.cs | 4 ++-- 3 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs index 957d705c5..724fabecd 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs @@ -80,9 +80,7 @@ public async ValueTask BuildAsync() AssertWeb3EnvironmentBound(serviceProvider); var web3 = new Web3(serviceProvider); - - var initializableWeb3 = (IInitializableWeb3)web3; - await initializableWeb3.InitializeAsync(); + await web3.InitializeAsync(); return web3; } diff --git a/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs b/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs deleted file mode 100644 index 16cb54bf2..000000000 --- a/src/ChainSafe.Gaming/Web3/Core/IInitializableWeb3.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace ChainSafe.Gaming.Web3.Core -{ - internal interface IInitializableWeb3 - { - ValueTask InitializeAsync(); - } -} \ No newline at end of file diff --git a/src/ChainSafe.Gaming/Web3/Core/Web3.cs b/src/ChainSafe.Gaming/Web3/Core/Web3.cs index 85b90895e..771159b56 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Web3.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Web3.cs @@ -14,7 +14,7 @@ namespace ChainSafe.Gaming.Web3 /// Facade for all Web3-related services. /// Use this as an entry point to all SDK features. /// - public class Web3 : IAsyncDisposable, IInitializableWeb3 + public class Web3 : IAsyncDisposable { private readonly ServiceProvider serviceProvider; private readonly IRpcProvider? rpcProvider; @@ -84,7 +84,7 @@ async ValueTask IAsyncDisposable.DisposeAsync() GC.SuppressFinalize(this); } - async ValueTask IInitializableWeb3.InitializeAsync() + internal async ValueTask InitializeAsync() { foreach (var lifecycleParticipant in serviceProvider.GetServices()) { From ef15fe7e34fc51038cf0fe8cf373578a74aa7d99 Mon Sep 17 00:00:00 2001 From: oleksandr Date: Mon, 23 Oct 2023 18:05:49 +0300 Subject: [PATCH 6/7] Fixed Docstring for Web3 folder --- .../NoOpAnalyticsClientExtensions.cs | 6 +++ .../Web3/Core/Build/Web3Builder.cs | 15 ++++++- .../Build/Web3ServiceCollectionExtensions.cs | 44 ++++++++++--------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs index e43495d2f..2482d8e35 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Analytics/NoOpAnalyticsClientExtensions.cs @@ -10,6 +10,7 @@ public static class NoOpAnalyticsClientExtensions /// /// Disables analytics for the instance. /// + /// The Web3 service collection. /// Service collection to enable fluent syntax. public static IWeb3ServiceCollection DisableAnalytics(this IWeb3ServiceCollection serviceCollection) { @@ -17,6 +18,11 @@ public static IWeb3ServiceCollection DisableAnalytics(this IWeb3ServiceCollectio return serviceCollection; } + /// + /// Returns true if analytics are disabled. + /// + /// The Web3 service collection. + /// True if analytics are disabled. public static bool AnalyticsDisabled(this IWeb3ServiceCollection serviceCollection) { return serviceCollection.Any(d => diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs index 724fabecd..3e2a25ae6 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3Builder.cs @@ -27,23 +27,34 @@ private Web3Builder() .AddSingleton(); } + /// + /// Initializes a new instance of the class. + /// + /// Project config to use with the resulting Web3 instance. + /// Chain config to use with the resulting Web3 instance. + /// One of the arguments is null. public Web3Builder(IProjectConfig projectConfig, IChainConfig chainConfig) : this() { if (projectConfig == null) { - throw new Web3Exception($"{nameof(IProjectConfig)} is required for Web3 to work."); + throw new ArgumentNullException(nameof(projectConfig), $"{nameof(IProjectConfig)} is required for Web3 to work."); } if (chainConfig == null) { - throw new Web3Exception($"{nameof(IChainConfig)} is required for Web3 to work."); + throw new ArgumentNullException(nameof(chainConfig), $"{nameof(IChainConfig)} is required for Web3 to work."); } serviceCollection.AddSingleton(projectConfig); serviceCollection.AddSingleton(chainConfig); } + /// + /// Initializes a new instance of the class. + /// + /// Complete project config to use with the resulting Web3 instance. + /// "projectConfig" is null. public Web3Builder(ICompleteProjectConfig projectConfig) : this(projectConfig, projectConfig) { diff --git a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs index 24cfb7961..17aae2ab2 100644 --- a/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs +++ b/src/ChainSafe.Gaming/Web3/Core/Build/Web3ServiceCollectionExtensions.cs @@ -9,7 +9,8 @@ public static class Web3ServiceCollectionExtensions /// /// Assert that service of the specified type was not yet registered. /// - /// Type of the service. + /// The type of the service. + /// The Web3 service collection. /// Service of the specified type was already bound. public static void AssertServiceNotBound(this IWeb3ServiceCollection services) { @@ -24,8 +25,9 @@ public static void AssertServiceNotBound(this IWeb3ServiceCollection services /// /// Assert that configuration object of the specified type was not yet registered. /// - /// Type of the configuration object. - /// Configuration object of the specified type was already bound. + /// The type of the configuration object. + /// The Web3 service collection. + /// The configuration object of the specified type was already bound. public static void AssertConfigurationNotBound(this IWeb3ServiceCollection services) { var assertType = typeof(T); @@ -39,9 +41,10 @@ public static void AssertConfigurationNotBound(this IWeb3ServiceCollection se /// /// Register the specified implementation using 2 contract types. /// - /// First contract type. - /// Second contract type. - /// Implementation type. + /// The first contract type. + /// The second contract type. + /// The implementation type. + /// The Web3 service collection. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class @@ -62,11 +65,11 @@ public static void AddSingleton(this /// /// Register the specified implementation for 2 contract types using the factory method. /// - /// Service collection. - /// Factory method. - /// First contract type. - /// Second contract type. - /// Implementation type. + /// The Web3 service collection. + /// The factory method. + /// The first contract type. + /// The second contract type. + /// The implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class @@ -80,10 +83,11 @@ public static void AddSingleton(this /// /// Register the specified implementation using 3 contract types. /// - /// First contract type. - /// Second contract type. - /// Third contract type. - /// Implementation type. + /// The Web3 service collection. + /// The first contract type. + /// The second contract type. + /// The third contract type. + /// The implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection) where TInterface1 : class where TInterface2 : class @@ -99,12 +103,12 @@ public static void AddSingleton /// Register the specified implementation for 3 contract types using the factory method. /// - /// Service collection. + /// The Web3 service collection. /// Factory method. - /// First contract type. - /// Second contract type. - /// Third contract type. - /// Implementation type. + /// The first contract type. + /// The second contract type. + /// The third contract type. + /// The implementation type. public static void AddSingleton(this IWeb3ServiceCollection serviceCollection, Func implementationFactory) where TInterface1 : class where TInterface2 : class From 6f0120688d8dc843cf4901d024a0fa839f659f7b Mon Sep 17 00:00:00 2001 From: Peter Kalambet Date: Wed, 25 Oct 2023 14:47:56 +0200 Subject: [PATCH 7/7] retrigger checks