diff --git a/CryptoExchange.Net/Converters/SystemTextJson/CommaSplitStringConverter.cs b/CryptoExchange.Net/Converters/SystemTextJson/CommaSplitStringConverter.cs new file mode 100644 index 0000000..b3ec015 --- /dev/null +++ b/CryptoExchange.Net/Converters/SystemTextJson/CommaSplitStringConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace CryptoExchange.Net.Converters.SystemTextJson +{ + /// + /// Converter for comma separated string values + /// + public class CommaSplitStringConverter : JsonConverter + { + /// + public override string[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var str = reader.GetString(); + if (string.IsNullOrEmpty(str)) + return []; + + return str!.Split(',').ToArray() ?? []; + } + + /// + public override void Write(Utf8JsonWriter writer, string[] value, JsonSerializerOptions options) + { + writer.WriteStringValue(string.Join(",", value)); + } + } +} diff --git a/CryptoExchange.Net/ExtensionMethods.cs b/CryptoExchange.Net/ExtensionMethods.cs index 6f78e63..7dd272c 100644 --- a/CryptoExchange.Net/ExtensionMethods.cs +++ b/CryptoExchange.Net/ExtensionMethods.cs @@ -74,8 +74,13 @@ namespace CryptoExchange.Net { if (serializationType == ArrayParametersSerialization.Array) { - foreach(var entry in (object[])parameter.Value) + bool firstArrayValue = true; + foreach (var entry in (object[])parameter.Value) { + if (!firstArrayValue) + uriString.Append('&'); + firstArrayValue = false; + uriString.Append(parameter.Key); uriString.Append("[]="); if (urlEncodeValues) @@ -611,6 +616,26 @@ namespace CryptoExchange.Net return services; } + + /// + /// Convert a hex encoded string to byte array + /// + /// + /// + public static byte[] HexStringToBytes(this string hexString) + { + if (hexString.StartsWith("0x")) + hexString = hexString.Substring(2); + + byte[] bytes = new byte[hexString.Length / 2]; + for (int i = 0; i < hexString.Length; i += 2) + { + string hexSubstring = hexString.Substring(i, 2); + bytes[i / 2] = Convert.ToByte(hexSubstring, 16); + } + + return bytes; + } } } diff --git a/CryptoExchange.Net/Objects/ParameterCollection.cs b/CryptoExchange.Net/Objects/ParameterCollection.cs index daa011d..d49f8fa 100644 --- a/CryptoExchange.Net/Objects/ParameterCollection.cs +++ b/CryptoExchange.Net/Objects/ParameterCollection.cs @@ -96,6 +96,23 @@ namespace CryptoExchange.Net.Objects base.Add(key, value.Value.ToString(CultureInfo.InvariantCulture)); } + /// + /// Add a DateTime value as string + /// + public void AddString(string key, DateTime value) + { + base.Add(key, value.ToString("yyyy-MM-ddTHH:mm:ssZ")); + } + + /// + /// Add a DateTime value as string. Not added if value is null + /// + public void AddOptionalString(string key, DateTime? value) + { + if (value != null) + base.Add(key, value.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")); + } + /// /// Add a datetime value as milliseconds timestamp /// @@ -241,6 +258,45 @@ namespace CryptoExchange.Net.Objects base.Add(key, int.Parse(stringVal)); } } + + /// + /// Add key as comma separated values + /// + public void AddCommaSeparated(string key, IEnumerable values) + { + base.Add(key, string.Join(",", values)); + } + + /// + /// Add key as comma separated values if there are values provided + /// + public void AddOptionalCommaSeparated(string key, IEnumerable? values) + { + if (values == null || !values.Any()) + return; + + base.Add(key, string.Join(",", values)); + } + + /// + /// Add key as boolean lower case value + /// + public void AddBoolString(string key, bool value) + { + base.Add(key, value.ToString().ToLower()); + } + + /// + /// Add key as boolean lower case value if it's not null + /// + public void AddOptionalBoolString(string key, bool? value) + { + if (value == null) + return; + + base.Add(key, value.ToString()!.ToLower()); + } + /// /// Set the request body. Can be used to specify a simple value or array as the body instead of an object