diff --git a/CryptoExchange.Net.UnitTests/ExchangeHelpersTests.cs b/CryptoExchange.Net.UnitTests/ExchangeHelpersTests.cs
index bdb8501..403f85e 100644
--- a/CryptoExchange.Net.UnitTests/ExchangeHelpersTests.cs
+++ b/CryptoExchange.Net.UnitTests/ExchangeHelpersTests.cs
@@ -1,6 +1,7 @@
using CryptoExchange.Net.Objects;
using NUnit.Framework;
using NUnit.Framework.Legacy;
+using System.Diagnostics;
using System.Globalization;
namespace CryptoExchange.Net.UnitTests
@@ -70,5 +71,20 @@ namespace CryptoExchange.Net.UnitTests
var result = ExchangeHelpers.Normalize(input);
Assert.That(expected == result.ToString(CultureInfo.InvariantCulture));
}
+
+ [Test]
+ [TestCase("123", "BKR", 32, true, "BKR|JK|123")]
+ [TestCase("123", "BKR", 32, false, "123")]
+ [TestCase("123123123123123123123123123123", "BKR", 32, true, "123123123123123123123123123123")] // 30
+ [TestCase("123123123123123123123123123", "BKR", 32, true, "123123123123123123123123123")] // 27
+ [TestCase("1231231231231231231231231", "BKR", 32, true, "BKR|JK|1231231231231231231231231")] // 25
+ [TestCase(null, "BKR", 32, true, null)]
+ public void ApplyBrokerIdTests(string clientOrderId, string brokerId, int maxLength, bool allowValueAdjustement, string expected)
+ {
+ var result = LibraryHelpers.ApplyBrokerId(clientOrderId, brokerId, maxLength, allowValueAdjustement);
+
+ if (expected != null)
+ Assert.That(result, Is.EqualTo(expected));
+ }
}
}
diff --git a/CryptoExchange.Net/Converters/SystemTextJson/JsonConverterCtorAttribute.cs b/CryptoExchange.Net/Converters/SystemTextJson/JsonConverterCtorAttribute.cs
new file mode 100644
index 0000000..48c4240
--- /dev/null
+++ b/CryptoExchange.Net/Converters/SystemTextJson/JsonConverterCtorAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Text.Json.Serialization;
+
+namespace CryptoExchange.Net.Converters.SystemTextJson
+{
+ ///
+ /// Attribute for allowing specifying a JsonConverter with constructor parameters
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Property)]
+ public class JsonConverterCtorAttribute : JsonConverterAttribute where T : JsonConverter
+ {
+ private readonly object[] _parameters;
+
+ ///
+ /// ctor
+ ///
+ public JsonConverterCtorAttribute(params object[] parameters) => _parameters = parameters;
+
+ ///
+ public override JsonConverter CreateConverter(Type typeToConvert)
+ {
+ return (T)Activator.CreateInstance(typeof(T), _parameters);
+ }
+ }
+
+}
diff --git a/CryptoExchange.Net/Converters/SystemTextJson/ReplaceConverter.cs b/CryptoExchange.Net/Converters/SystemTextJson/ReplaceConverter.cs
new file mode 100644
index 0000000..5976387
--- /dev/null
+++ b/CryptoExchange.Net/Converters/SystemTextJson/ReplaceConverter.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace CryptoExchange.Net.Converters.SystemTextJson
+{
+ ///
+ /// Replace a value on a string property
+ ///
+ public class ReplaceConverter : JsonConverter
+ {
+ private readonly (string ValueToReplace, string ValueToReplaceWith)[] _replacementSets;
+
+ ///
+ /// ctor
+ ///
+ public ReplaceConverter(params string[] replaceSets)
+ {
+ _replacementSets = replaceSets.Select(x =>
+ {
+ var split = x.Split(new string[] { "->" }, StringSplitOptions.None);
+ if (split.Length != 2)
+ throw new ArgumentException("Invalid replacement config");
+ return (split[0], split[1]);
+ }).ToArray();
+ }
+
+ ///
+ public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var value = reader.GetString();
+ foreach (var set in _replacementSets)
+ value = value?.Replace(set.ValueToReplace, set.ValueToReplaceWith);
+ return value;
+ }
+
+ ///
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => writer.WriteStringValue(value);
+ }
+}
diff --git a/CryptoExchange.Net/CryptoExchange.Net.csproj b/CryptoExchange.Net/CryptoExchange.Net.csproj
index 6ff68b9..b3a0935 100644
--- a/CryptoExchange.Net/CryptoExchange.Net.csproj
+++ b/CryptoExchange.Net/CryptoExchange.Net.csproj
@@ -20,7 +20,7 @@
true
https://github.com/JKorf/CryptoExchange.Net?tab=readme-ov-file#release-notes
enable
- 10.0
+ 12.0
MIT
diff --git a/CryptoExchange.Net/LibraryHelpers.cs b/CryptoExchange.Net/LibraryHelpers.cs
new file mode 100644
index 0000000..ba8b008
--- /dev/null
+++ b/CryptoExchange.Net/LibraryHelpers.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CryptoExchange.Net
+{
+ ///
+ /// Helpers for client libraries
+ ///
+ public static class LibraryHelpers
+ {
+ ///
+ /// Client order id seperator
+ ///
+ public const string ClientOrderIdSeperator = "|JK|";
+
+ ///
+ /// Apply broker id to a client order id
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string ApplyBrokerId(string? clientOrderId, string brokerId, int maxLength, bool allowValueAdjustement)
+ {
+ var reservedLength = brokerId.Length + ClientOrderIdSeperator.Length;
+
+ if ((clientOrderId?.Length + reservedLength) > maxLength)
+ return clientOrderId!;
+
+ if (!string.IsNullOrEmpty(clientOrderId))
+ {
+ if (allowValueAdjustement)
+ clientOrderId = brokerId + ClientOrderIdSeperator + clientOrderId;
+
+ return clientOrderId!;
+ }
+ else
+ {
+ clientOrderId = ExchangeHelpers.AppendRandomString(brokerId + ClientOrderIdSeperator, maxLength);
+ }
+
+ return clientOrderId;
+ }
+ }
+}