diff --git a/TonSdk.Client/src/HttpApi/HttpsApi.cs b/TonSdk.Client/src/HttpApi/HttpsApi.cs index fda9b9e..c16382a 100644 --- a/TonSdk.Client/src/HttpApi/HttpsApi.cs +++ b/TonSdk.Client/src/HttpApi/HttpsApi.cs @@ -1,6 +1,8 @@ using Newtonsoft.Json; using System; +using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Threading.Tasks; using TonSdk.Core; using TonSdk.Core.Block; @@ -15,7 +17,7 @@ public class HttpApiParameters public int? Timeout { get; set; } public string ApiKey { get; set; } } - + public class HttpApi : IDisposable { private readonly HttpClient _httpClient; @@ -27,7 +29,35 @@ internal HttpApi(HttpParameters httpApiParameters) throw new ArgumentNullException("Endpoint field in Http options cannot be null."); } - _httpClient = new HttpClient(); + if (httpApiParameters.Proxy != null) + { + WebProxy webProxy = new WebProxy + { + Address = new Uri( httpApiParameters.Proxy.ProxyType switch + { + ProxyType.HTTP => "http://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.HTTPS => "https://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks4 => "socks4://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks5 => "socks5://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + _ => throw new ArgumentOutOfRangeException() + }), + Credentials = new NetworkCredential( + userName: httpApiParameters.Proxy.UserName, + password: httpApiParameters.Proxy.Password + ) + }; + HttpClientHandler httpClientHandler = new HttpClientHandler + { + Proxy = webProxy + }; + + _httpClient = new HttpClient(httpClientHandler); + + } + else + { + _httpClient = new HttpClient(); + } _httpClient.Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(httpApiParameters.Timeout ?? 30000)); //httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json"); diff --git a/TonSdk.Client/src/HttpApi/HttpsApiV3.cs b/TonSdk.Client/src/HttpApi/HttpsApiV3.cs index 40d1758..3c2bd1a 100644 --- a/TonSdk.Client/src/HttpApi/HttpsApiV3.cs +++ b/TonSdk.Client/src/HttpApi/HttpsApiV3.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using TonSdk.Client.Stack; @@ -23,8 +24,35 @@ public HttpApiV3(HttpParameters httpApiParameters) throw new ArgumentNullException("Endpoint field in Http options cannot be null."); } - _httpClient = new HttpClient(); + if (httpApiParameters.Proxy != null) + { + WebProxy webProxy = new WebProxy + { + Address = new Uri( httpApiParameters.Proxy.ProxyType switch + { + ProxyType.HTTP => "http://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.HTTPS => "https://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks4 => "socks4://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks5 => "socks5://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + _ => throw new ArgumentOutOfRangeException() + }), + Credentials = new NetworkCredential( + userName: httpApiParameters.Proxy.UserName, + password: httpApiParameters.Proxy.Password + ) + }; + HttpClientHandler httpClientHandler = new HttpClientHandler + { + Proxy = webProxy + }; + _httpClient = new HttpClient(httpClientHandler); + + } + else + { + _httpClient = new HttpClient(); + } _httpClient.Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(httpApiParameters.Timeout ?? 30000)); _httpClient.DefaultRequestHeaders.Accept.Clear(); diff --git a/TonSdk.Client/src/HttpApi/HttpsWhales.cs b/TonSdk.Client/src/HttpApi/HttpsWhales.cs index 41bc985..271400c 100644 --- a/TonSdk.Client/src/HttpApi/HttpsWhales.cs +++ b/TonSdk.Client/src/HttpApi/HttpsWhales.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using TonSdk.Core; @@ -21,8 +22,35 @@ internal HttpWhales(HttpParameters httpApiParameters) throw new ArgumentNullException("Endpoint field in Http options cannot be null."); } - _httpClient = new HttpClient(); + if (httpApiParameters.Proxy != null) + { + WebProxy webProxy = new WebProxy + { + Address = new Uri( httpApiParameters.Proxy.ProxyType switch + { + ProxyType.HTTP => "http://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.HTTPS => "https://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks4 => "socks4://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + ProxyType.Socks5 => "socks5://" + httpApiParameters.Proxy.Ip + ":" + httpApiParameters.Proxy.Port, + _ => throw new ArgumentOutOfRangeException() + }), + Credentials = new NetworkCredential( + userName: httpApiParameters.Proxy.UserName, + password: httpApiParameters.Proxy.Password + ) + }; + HttpClientHandler httpClientHandler = new HttpClientHandler + { + Proxy = webProxy + }; + _httpClient = new HttpClient(httpClientHandler); + + } + else + { + _httpClient = new HttpClient(); + } _httpClient.Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(httpApiParameters.Timeout ?? 30000)); //httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json"); diff --git a/TonSdk.Client/src/Models/Models.cs b/TonSdk.Client/src/Models/Models.cs index bad3d40..4c26fa0 100644 --- a/TonSdk.Client/src/Models/Models.cs +++ b/TonSdk.Client/src/Models/Models.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Net; +using System.Reflection.Metadata; using System.Threading.Tasks; using TonSdk.Client.Stack; using TonSdk.Core; @@ -16,6 +18,14 @@ public enum TonClientType } + public enum ProxyType + { + Socks5, + Socks4, + HTTP, + HTTPS + } + public interface ITonClientOptions {} public class HttpParameters : ITonClientOptions @@ -23,6 +33,7 @@ public class HttpParameters : ITonClientOptions public string Endpoint { get; set; } public int? Timeout { get; set; } public string ApiKey { get; set; } + public Proxy? Proxy { get; set; } } public class LiteClientParameters : ITonClientOptions @@ -38,4 +49,47 @@ public LiteClientParameters(string host, int port, string peerPublicKey) PeerPublicKey = peerPublicKey; } } + + /// + /// Credentials for connecting to the proxy + /// + public partial class Proxy : ITonClientOptions + { + /// + /// Ip address of the proxy server + /// + public IPAddress Ip { get; set; } + + private int _port; + + /// + /// Port number of the proxy server + /// + /// The proxy port number goes beyond 1-65536 + public int Port + { + set + { + if (value < 1 || value > 65536) + throw new Exception("The proxy port number goes beyond 1-65536"); + _port = value; + } + get => _port; + } + + /// + /// The user's name of the credentials + /// + public string UserName { get; set; } + + /// + /// The password's of the credentials + /// + public string Password { get; set; } + + /// + /// Type of proxy server protocol + /// + public ProxyType ProxyType { get; set; } + } } \ No newline at end of file diff --git a/TonSdk.Client/src/Models/Proxy.cs b/TonSdk.Client/src/Models/Proxy.cs new file mode 100644 index 0000000..1b6547d --- /dev/null +++ b/TonSdk.Client/src/Models/Proxy.cs @@ -0,0 +1,30 @@ +using Org.BouncyCastle.Crypto.Parameters; + +namespace TonSdk.Client +{ + public partial class Proxy + { + public override bool Equals(object obj) + { + Proxy tmpProxy = obj as Proxy; + if (tmpProxy == null) return false; + + if (Ip != tmpProxy.Ip) return false; + if (Port != tmpProxy.Port) return false; + if (UserName != tmpProxy.UserName) return false; + if (Password != tmpProxy.Password) return false; + if (ProxyType != tmpProxy.ProxyType) return false; + return true; + } + + public override int GetHashCode() + { + int hashCode = Ip.GetHashCode(); + hashCode = 31 * hashCode + Port.GetHashCode(); + hashCode = 31 * hashCode + UserName.GetHashCode(); + hashCode = 31 * hashCode + Password.GetHashCode(); + hashCode = 31 * hashCode + ProxyType.GetHashCode(); + return hashCode; + } + } +} \ No newline at end of file diff --git a/TonSdk.Client/test/Client.test.cs b/TonSdk.Client/test/Client.test.cs index 23b9b4d..accc128 100644 --- a/TonSdk.Client/test/Client.test.cs +++ b/TonSdk.Client/test/Client.test.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using System.Numerics; using System.Threading.Tasks; using NUnit.Framework; @@ -220,4 +221,39 @@ public async Task Test_JettonGetWalletAddress() Assert.That((await client_lite.Jetton.GetWalletAddress(new Address("EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE"), new Address("EQAEnqomwC3dg323OcdgUsvk3T38VvYawX8q6x38ulfnCn7b"))).Equals(new Address("EQA_d9IqxSQCSuwZIvH0RRSUMvWK4qrvl5ZH_nOHFH7Gxifq")), Is.EqualTo(true)); Assert.That((await client_lite.Jetton.GetWalletAddress(new Address("EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE"), new Address("EQAEnqomwC3dg323OcdgUsvk3T38VvYawX8q6x38ulfnCn7b"))).Equals(new Address("EQAEnqomwC3dg323OcdgUsvk3T38VvYawX8q6x38ulfnCn7b")), Is.EqualTo(false)); } + + [Test] + public void Test_ProxyClass() + { + Proxy proxy1 = new Proxy + { + Ip = IPAddress.Parse("1.1.1.1"), + Port = 22222, + UserName = "WhoIsIt?", + Password = "54321" + }; + + Proxy proxy2 = new Proxy + { + Ip = IPAddress.Parse("1.1.1.1"), + Port = 22222, + UserName = "WhoIsIt?", + Password = "54321" + }; + + Proxy proxy3 = new Proxy + { + Ip = IPAddress.Parse("123.123.123.123"), + Port = 33333, + UserName = "ItsMe,Mario", + Password = "51423" + }; + + Assert.That(proxy1.GetHashCode(), Is.EqualTo(-1512725739)); + Assert.That(proxy2.GetHashCode(), Is.EqualTo(-1512725739)); + Assert.That(proxy3.GetHashCode(), Is.EqualTo(168523034)); + + Assert.That(proxy1.Equals(proxy2), Is.True); + Assert.That(proxy1.Equals(proxy3), Is.False); + } }