diff --git a/Huobi.Net/Clients/SpotApi/HuobiSocketClientSpotApi.cs b/Huobi.Net/Clients/SpotApi/HuobiSocketClientSpotApi.cs index e0053181..91cd2d90 100644 --- a/Huobi.Net/Clients/SpotApi/HuobiSocketClientSpotApi.cs +++ b/Huobi.Net/Clients/SpotApi/HuobiSocketClientSpotApi.cs @@ -115,7 +115,7 @@ public async Task> SubscribeToKlineUpdatesAsync(s { symbol = symbol.ValidateHuobiSymbol(); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.kline.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.kline.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } @@ -147,7 +147,7 @@ public async Task> SubscribeToPartialOrderBookUpd symbol = symbol.ValidateHuobiSymbol(); mergeStep.ValidateIntBetween(nameof(mergeStep), 0, 5); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.depth.step{mergeStep}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.depth.step{mergeStep}", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } @@ -157,7 +157,7 @@ public async Task> SubscribeToPartialOrderBookUpd symbol = symbol.ValidateHuobiSymbol(); levels.ValidateIntValues(nameof(levels), 5, 10, 20); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.mbp.refresh.{levels}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.mbp.refresh.{levels}", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } @@ -167,7 +167,7 @@ public async Task> SubscribeToOrderBookChangeUpda symbol = symbol.ValidateHuobiSymbol(); levels.ValidateIntValues(nameof(levels), 5, 20, 150, 400); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.mbp.{levels}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.mbp.{levels}", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("feed"), subscription, ct).ConfigureAwait(false); } @@ -185,7 +185,7 @@ public async Task>> GetTradeHist public async Task> SubscribeToTradeUpdatesAsync(string symbol, Action> onData, CancellationToken ct = default) { symbol = symbol.ValidateHuobiSymbol(); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.trade.detail", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.trade.detail", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } @@ -207,7 +207,7 @@ public async Task> GetSymbolDetailsAsync(string s public async Task> SubscribeToSymbolDetailUpdatesAsync(string symbol, Action> onData, CancellationToken ct = default) { symbol = symbol.ValidateHuobiSymbol(); - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.detail", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.detail", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } @@ -221,14 +221,14 @@ public async Task> SubscribeToTickerUpdatesAsync( /// public async Task> SubscribeToTickerUpdatesAsync(string symbol, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.ticker", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.ticker", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToBestOfferUpdatesAsync(string symbol, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{symbol}.bbo", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{symbol}.bbo", x => onData(x.WithSymbol(symbol)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws"), subscription, ct).ConfigureAwait(false); } diff --git a/Huobi.Net/Clients/UsdtMarginSwapApi/HuobiSocketClientUsdtMarginSwapApi.cs b/Huobi.Net/Clients/UsdtMarginSwapApi/HuobiSocketClientUsdtMarginSwapApi.cs index e46d65f4..66b82905 100644 --- a/Huobi.Net/Clients/UsdtMarginSwapApi/HuobiSocketClientUsdtMarginSwapApi.cs +++ b/Huobi.Net/Clients/UsdtMarginSwapApi/HuobiSocketClientUsdtMarginSwapApi.cs @@ -78,77 +78,77 @@ protected override AuthenticationProvider CreateAuthenticationProvider(ApiCreden /// public async Task> SubscribeToKlineUpdatesAsync(string contractCode, KlineInterval period, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.kline.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.kline.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToOrderBookUpdatesAsync(string contractCode, int mergeStep, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.depth.step" + mergeStep, onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.depth.step" + mergeStep, x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToIncrementalOrderBookUpdatesAsync(string contractCode, bool snapshot, int limit, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.depth.size_{limit}.high_freq", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.depth.size_{limit}.high_freq", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToSymbolTickerUpdatesAsync(string contractCode, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.detail", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.detail", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToBestOfferUpdatesAsync(string contractCode, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.bbo", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.bbo", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToTradeUpdatesAsync(string contractCode, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.trade.detail", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.trade.detail", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("linear-swap-ws"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToIndexKlineUpdatesAsync(string contractCode, KlineInterval period, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.index.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.index.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws_index"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToPremiumIndexKlineUpdatesAsync(string contractCode, KlineInterval period, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.premium_index.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.premium_index.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws_index"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToEstimatedFundingRateKlineUpdatesAsync(string contractCode, KlineInterval period, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.estimated_rate.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.estimated_rate.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws_index"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToBasisUpdatesAsync(string contractCode, KlineInterval period, string priceType, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.basis.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}.{priceType}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.basis.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}.{priceType}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws_index"), subscription, ct).ConfigureAwait(false); } /// public async Task> SubscribeToMarkPriceKlineUpdatesAsync(string contractCode, KlineInterval period, Action> onData, CancellationToken ct = default) { - var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.mark_price.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", onData, false); + var subscription = new HuobiSubscription(_logger, $"market.{contractCode.ToUpperInvariant()}.mark_price.{JsonConvert.SerializeObject(period, new PeriodConverter(false))}", x => onData(x.WithSymbol(contractCode)), false); return await SubscribeAsync(BaseAddress.AppendPath("ws_index"), subscription, ct).ConfigureAwait(false); } diff --git a/Huobi.Net/Huobi.Net.csproj b/Huobi.Net/Huobi.Net.csproj index 898b68e2..55039801 100644 --- a/Huobi.Net/Huobi.Net.csproj +++ b/Huobi.Net/Huobi.Net.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netstandard2.1 enable @@ -48,7 +48,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Huobi.Net/HuobiAuthenticationProvider.cs b/Huobi.Net/HuobiAuthenticationProvider.cs index 5b2d7acb..58e4b81d 100644 --- a/Huobi.Net/HuobiAuthenticationProvider.cs +++ b/Huobi.Net/HuobiAuthenticationProvider.cs @@ -26,36 +26,37 @@ public HuobiAuthenticationProvider(ApiCredentials credentials, bool signPublicRe _signPublicRequests = signPublicRequests; } - public override void AuthenticateRequest(RestApiClient apiClient, + public override void AuthenticateRequest( + RestApiClient apiClient, Uri uri, HttpMethod method, - IDictionary uriParams, - IDictionary bodyParams, + IDictionary uriParameters, + IDictionary bodyParameters, Dictionary headers, bool auth, ArrayParametersSerialization arraySerialization, HttpMethodParameterPosition parameterPosition, - RequestBodyFormat bodyFormat) + RequestBodyFormat requestBodyFormat) { if (!auth && !_signPublicRequests) return; // These are always in the uri - uriParams.Add("AccessKeyId", _credentials.Key!.GetString()); - uriParams.Add("SignatureMethod", "HmacSHA256"); - uriParams.Add("SignatureVersion", 2); - uriParams.Add("Timestamp", GetTimestamp(apiClient).ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture)); + uriParameters.Add("AccessKeyId", _credentials.Key!.GetString()); + uriParameters.Add("SignatureMethod", "HmacSHA256"); + uriParameters.Add("SignatureVersion", 2); + uriParameters.Add("Timestamp", GetTimestamp(apiClient).ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture)); var absolutePath = uri.AbsolutePath; if (absolutePath.StartsWith("/api")) // Russian api has /api prefix which shouldn't be part of the signature absolutePath = absolutePath.Substring(4); - var sortedParameters = uriParams.OrderBy(kv => Encoding.UTF8.GetBytes(WebUtility.UrlEncode(kv.Key)!), new ByteOrderComparer()); + var sortedParameters = uriParameters.OrderBy(kv => Encoding.UTF8.GetBytes(WebUtility.UrlEncode(kv.Key)!), new ByteOrderComparer()); var paramString = uri.SetParameters(sortedParameters, arraySerialization).Query.Replace("?", ""); paramString = new Regex(@"%[a-f0-9]{2}").Replace(paramString, m => m.Value.ToUpperInvariant()); var signData = $"{method}\n{uri.Host}\n{absolutePath}\n{paramString}"; - uriParams.Add("Signature", SignHMACSHA256(signData, SignOutputType.Base64)); + uriParameters.Add("Signature", SignHMACSHA256(signData, SignOutputType.Base64)); } public HuobiAuthParams GetWebsocketAuthentication(Uri uri) diff --git a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiAccountSubscription.cs b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiAccountSubscription.cs index 67494828..c8c42fdf 100644 --- a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiAccountSubscription.cs +++ b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiAccountSubscription.cs @@ -36,7 +36,7 @@ public HuobiAccountSubscription(ILogger logger, string topic, Action message) { var update = (HuobiDataEvent)message.Data; - _handler.Invoke(message.As(update.Data, update.Channel)); + _handler.Invoke(message.As(update.Data, update.Channel, null, SocketUpdateType.Update)); return new CallResult(null); } diff --git a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderDetailsSubscription.cs b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderDetailsSubscription.cs index 2428204f..ec529cce 100644 --- a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderDetailsSubscription.cs +++ b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderDetailsSubscription.cs @@ -44,9 +44,9 @@ public override CallResult DoHandleMessage(SocketConnection connection, DataEven { var data = message.Data; if (data is HuobiDataEvent tradeEvent) - _onOrderMatch?.Invoke(message.As(tradeEvent.Data, tradeEvent.Channel)); + _onOrderMatch?.Invoke(message.As(tradeEvent.Data, tradeEvent.Channel, tradeEvent.Data.Symbol, SocketUpdateType.Update)); if (data is HuobiDataEvent cancelEvent) - _onOrderCancel?.Invoke(message.As(cancelEvent.Data, cancelEvent.Channel)); + _onOrderCancel?.Invoke(message.As(cancelEvent.Data, cancelEvent.Channel, cancelEvent.Data.Symbol, SocketUpdateType.Update)); return new CallResult(null); } diff --git a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderSubscription.cs b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderSubscription.cs index c13d42b3..33bad2dd 100644 --- a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderSubscription.cs +++ b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiOrderSubscription.cs @@ -53,15 +53,15 @@ public override CallResult DoHandleMessage(SocketConnection connection, DataEven { var data = message.Data; if (data is HuobiDataEvent triggerFailEvent) - _onConditionalOrderTriggerFailure?.Invoke(message.As(triggerFailEvent.Data, triggerFailEvent.Channel)); + _onConditionalOrderTriggerFailure?.Invoke(message.As(triggerFailEvent.Data, triggerFailEvent.Channel, triggerFailEvent.Data.Symbol, SocketUpdateType.Update)); if (data is HuobiDataEvent orderEvent) - _onConditionalOrderCanceled?.Invoke(message.As(orderEvent.Data, orderEvent.Channel)); + _onConditionalOrderCanceled?.Invoke(message.As(orderEvent.Data, orderEvent.Channel, orderEvent.Data.Symbol, SocketUpdateType.Update)); if (data is HuobiDataEvent submitOrderEvent) - _onOrderSubmitted?.Invoke(message.As(submitOrderEvent.Data, submitOrderEvent.Channel)); + _onOrderSubmitted?.Invoke(message.As(submitOrderEvent.Data, submitOrderEvent.Channel, submitOrderEvent.Data.Symbol, SocketUpdateType.Update)); if (data is HuobiDataEvent matchOrderEvent) - _onOrderMatched?.Invoke(message.As(matchOrderEvent.Data, matchOrderEvent.Channel)); + _onOrderMatched?.Invoke(message.As(matchOrderEvent.Data, matchOrderEvent.Channel, matchOrderEvent.Data.Symbol, SocketUpdateType.Update)); if (data is HuobiDataEvent cancelOrderEvent) - _onOrderCancelation?.Invoke(message.As(cancelOrderEvent.Data, cancelOrderEvent.Channel)); + _onOrderCancelation?.Invoke(message.As(cancelOrderEvent.Data, cancelOrderEvent.Channel, cancelOrderEvent.Data.Symbol, SocketUpdateType.Update)); return new CallResult(null); } diff --git a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiSubscription.cs b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiSubscription.cs index 0ca87b11..da879844 100644 --- a/Huobi.Net/Objects/Sockets/Subscriptions/HuobiSubscription.cs +++ b/Huobi.Net/Objects/Sockets/Subscriptions/HuobiSubscription.cs @@ -38,7 +38,7 @@ public HuobiSubscription(ILogger logger, string topic, Action> hand public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var huobiEvent = (HuobiDataEvent)message.Data; - _handler.Invoke(message.As(huobiEvent.Data, huobiEvent.Channel)); + _handler.Invoke(message.As(huobiEvent.Data).WithStreamId(huobiEvent.Channel)); return new CallResult(null); } }