Skip to content

Commit 40fe69f

Browse files
youskypiftototiti
andauthored
Featurefix digifinex on get order details async (#819)
* fix OnGetOrderDetailsAsync * Update ExchangeDigifinexAPI.cs * Add websocket watchtickers for Digifinex --------- Co-authored-by: greg <toto@titi.com>
1 parent 90d116b commit 40fe69f

File tree

1 file changed

+163
-47
lines changed

1 file changed

+163
-47
lines changed

src/ExchangeSharp/API/Exchanges/Digifinex/ExchangeDigifinexAPI.cs

Lines changed: 163 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
13
using System;
24
using System.Collections.Generic;
35
using System.Linq;
4-
using System.Net.Http;
5-
using System.Text;
66
using System.Threading;
77
using System.Threading.Tasks;
8-
using Newtonsoft.Json.Linq;
98

109
namespace ExchangeSharp
1110
{
1211
public partial class ExchangeDigifinexAPI : ExchangeAPI
1312
{
1413
private string[] Urls =
1514
{
16-
"openapi.digifinex.com",
17-
"openapi.digifinex.vip", // these other URLs don't work anymore
15+
"openapi.digifinex.com",
16+
"openapi.digifinex.vip", // these other URLs don't work anymore
1817
"openapi.digifinex.xyz",
19-
};
18+
};
2019

2120
private string fastestUrl = null;
2221
private int failedUrlCount;
@@ -85,7 +84,7 @@ protected override async Task OnGetNonceOffset()
8584
var timeFaster = now - serverDate;
8685
timeWindow = "30"; // max latency of 30s
8786
NonceOffset = now - serverDate; // how much time to substract from Nonce when making a request
88-
//Console.WriteLine($"NonceOffset {GetHashCode()}: {NonceOffset}");
87+
//Console.WriteLine($"NonceOffset {GetHashCode()}: {NonceOffset}");
8988
}
9089
catch
9190
{
@@ -169,9 +168,7 @@ private async Task<ExchangeMarket> ParseExchangeMarketAsync(JToken x)
169168
};
170169
}
171170

172-
protected internal override async Task<
173-
IEnumerable<ExchangeMarket>
174-
> OnGetMarketSymbolsMetadataAsync()
171+
protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketSymbolsMetadataAsync()
175172
{
176173
await inited.Task;
177174
JToken obj = await MakeJsonRequestAsync<JToken>("markets");
@@ -189,9 +186,8 @@ protected override async Task<IEnumerable<string>> OnGetMarketSymbolsAsync()
189186
return (await GetMarketSymbolsMetadataAsync()).Select(x => x.MarketSymbol);
190187
}
191188

192-
private async Task<ExchangeTicker> ParseTickerAsync(JToken x)
189+
private async Task<ExchangeTicker> ParseTickerAsync(JToken t, JToken dateStr)
193190
{
194-
var t = x["ticker"][0];
195191
var symbol = t["symbol"].ToStringUpperInvariant();
196192
var (baseCurrency, quoteCurrency) = await ExchangeMarketSymbolToCurrenciesAsync(symbol);
197193

@@ -210,16 +206,34 @@ private async Task<ExchangeTicker> ParseTickerAsync(JToken x)
210206
QuoteCurrencyVolume = t["base_vol"].ConvertInvariant<decimal>(),
211207
BaseCurrencyVolume = t["vol"].ConvertInvariant<decimal>(),
212208
Timestamp = CryptoUtility.UnixTimeStampToDateTimeSeconds(
213-
x["date"].ConvertInvariant<long>()
209+
//t["date"].ConvertInvariant<long>()
210+
dateStr.ConvertInvariant<long>()
214211
),
215212
},
216213
};
217214
}
218215

216+
protected override async Task<IEnumerable<KeyValuePair<string, ExchangeTicker>>> OnGetTickersAsync()
217+
{
218+
List<KeyValuePair<string, ExchangeTicker>> tickers = new List<KeyValuePair<string, ExchangeTicker>>();
219+
JToken token = await MakeJsonRequestAsync<JToken>("/ticker");
220+
foreach (JToken tick in token["ticker"])
221+
{
222+
string marketSymbol = tick["symbol"].ToStringInvariant();
223+
tickers.Add(
224+
new KeyValuePair<string, ExchangeTicker>(
225+
marketSymbol,
226+
await ParseTickerAsync(tick, token["date"])
227+
)
228+
);
229+
}
230+
return tickers;
231+
}
232+
219233
protected override async Task<ExchangeTicker> OnGetTickerAsync(string marketSymbol)
220234
{
221235
JToken obj = await MakeJsonRequestAsync<JToken>($"/ticker?symbol={marketSymbol}");
222-
return await ParseTickerAsync(obj);
236+
return await ParseTickerAsync(obj["ticker"][0], obj["date"]);
223237
}
224238

225239
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(
@@ -388,9 +402,10 @@ protected override async Task<IEnumerable<ExchangeOrderResult>> OnGetOpenOrderDe
388402
);
389403
}
390404

391-
protected override async Task<
392-
IEnumerable<ExchangeOrderResult>
393-
> OnGetCompletedOrderDetailsAsync(string marketSymbol = null, DateTime? afterDate = null)
405+
protected override async Task<IEnumerable<ExchangeOrderResult>> OnGetCompletedOrderDetailsAsync(
406+
string marketSymbol = null,
407+
DateTime? afterDate = null
408+
)
394409
{
395410
Dictionary<string, object> payload = await GetNoncePayloadAsync();
396411
var url = "/spot/mytrades?limit=500";
@@ -443,7 +458,7 @@ protected override async Task<ExchangeOrderResult> OnGetOrderDetailsAsync(
443458
$"/spot/order?order_id={orderId}",
444459
payload: payload
445460
);
446-
var x = token["data"];
461+
var x = token["data"][0];
447462
return new ExchangeOrderResult
448463
{
449464
MarketSymbol = x["symbol"].ToStringUpperInvariant(),
@@ -458,7 +473,7 @@ protected override async Task<ExchangeOrderResult> OnGetOrderDetailsAsync(
458473
AveragePrice = x["avg_price"].ConvertInvariant<decimal>(),
459474
Amount = x["amount"].ConvertInvariant<decimal>(),
460475
AmountFilled = x["executed_amount"].ConvertInvariant<decimal>(),
461-
IsBuy = x["type"].ToStringLowerInvariant() == "buy",
476+
IsBuy = x["type"].ToStringLowerInvariant() == "buy_market",
462477
Result = ParseOrderStatus(x["status"]),
463478
};
464479
}
@@ -563,10 +578,86 @@ protected override async Task OnCancelOrderAsync(
563578

564579
#region WebSocket APIs
565580

566-
protected override async Task<IWebSocket> OnGetTradesWebSocketAsync(
567-
Func<KeyValuePair<string, ExchangeTrade>, Task> callback,
581+
protected override async Task<IWebSocket> OnGetTickersWebSocketAsync(
582+
Action<IReadOnlyCollection<KeyValuePair<string, ExchangeTicker>>> callback,
568583
params string[] marketSymbols
569584
)
585+
{
586+
await inited.Task;
587+
if (callback == null)
588+
{
589+
return null;
590+
}
591+
else if (marketSymbols == null || marketSymbols.Length == 0)
592+
{
593+
marketSymbols = (await GetMarketSymbolsAsync()).Take(30).ToArray();
594+
Logger.Warn("subscribing to the first 30 symbols");
595+
}
596+
return await ConnectPublicWebSocketAsync(
597+
string.Empty,
598+
async (_socket, msg) =>
599+
{
600+
JToken token = JToken.Parse(
601+
CryptoUtility
602+
.DecompressDeflate(
603+
(new ArraySegment<byte>(msg, 2, msg.Length - 2)).ToArray()
604+
)
605+
.ToStringFromUTF8()
606+
);
607+
// doesn't send error msgs - just disconnects
608+
if (token["method"].ToStringLowerInvariant() == "all_ticker.update")
609+
{
610+
var args = token["params"];
611+
var x = args as JArray;
612+
var tickers = new List<KeyValuePair<string, ExchangeTicker>>();
613+
614+
for (int i = 0; i < x.Count; i++)
615+
{
616+
var tick = x[i];
617+
var symbol = tick["symbol"].ToStringUpperInvariant();
618+
tickers.Add(new KeyValuePair<string, ExchangeTicker>(
619+
symbol,
620+
await this.ParseTickerWebSocketAsync(symbol, tick)
621+
)
622+
);
623+
}
624+
callback(tickers);
625+
}
626+
},
627+
async (_socket2) =>
628+
{
629+
var id = Interlocked.Increment(ref websocketMessageId);
630+
await _socket2.SendMessageAsync(
631+
new
632+
{
633+
id,
634+
method = "all_ticker.subscribe",
635+
@params = marketSymbols
636+
}
637+
);
638+
}
639+
);
640+
}
641+
642+
private async Task<ExchangeTicker> ParseTickerWebSocketAsync(string symbol, JToken token)
643+
{
644+
return await this.ParseTickerAsync(
645+
token,
646+
symbol,
647+
askKey: "best_ask",
648+
bidKey: "best_bid",
649+
lastKey: "last",
650+
baseVolumeKey: "base_volume_24h",
651+
quoteVolumeKey: "quote_volume_24h",
652+
timestampKey: "timestamp",
653+
TimestampType.UnixMilliseconds
654+
);
655+
}
656+
657+
protected override async Task<IWebSocket> OnGetTradesWebSocketAsync(
658+
Func<KeyValuePair<string, ExchangeTrade>, Task> callback,
659+
params string[] marketSymbols
660+
)
570661
{
571662
await inited.Task;
572663
if (callback == null)
@@ -601,12 +692,12 @@ params string[] marketSymbols
601692
// "id": null
602693
// }
603694
JToken token = JToken.Parse(
604-
CryptoUtility
605-
.DecompressDeflate(
606-
(new ArraySegment<byte>(msg, 2, msg.Length - 2)).ToArray()
607-
)
608-
.ToStringFromUTF8()
609-
);
695+
CryptoUtility
696+
.DecompressDeflate(
697+
(new ArraySegment<byte>(msg, 2, msg.Length - 2)).ToArray()
698+
)
699+
.ToStringFromUTF8()
700+
);
610701
// doesn't send error msgs - just disconnects
611702
if (token["method"].ToStringLowerInvariant() == "trades.update")
612703
{
@@ -658,13 +749,13 @@ await callback.Invoke(
658749
{
659750
var id = Interlocked.Increment(ref websocketMessageId);
660751
await _socket2.SendMessageAsync(
661-
new
662-
{
663-
id,
664-
method = "trades.subscribe",
665-
@params = marketSymbols
666-
}
667-
);
752+
new
753+
{
754+
id,
755+
method = "trades.subscribe",
756+
@params = marketSymbols
757+
}
758+
);
668759
}
669760
);
670761
}
@@ -716,12 +807,12 @@ params string[] marketSymbols
716807
// "id": null
717808
//}
718809
JToken token = JToken.Parse(
719-
CryptoUtility
720-
.DecompressDeflate(
721-
(new ArraySegment<byte>(msg, 2, msg.Length - 2)).ToArray()
722-
)
723-
.ToStringFromUTF8()
724-
);
810+
CryptoUtility
811+
.DecompressDeflate(
812+
(new ArraySegment<byte>(msg, 2, msg.Length - 2)).ToArray()
813+
)
814+
.ToStringFromUTF8()
815+
);
725816
if (token["method"].ToStringLowerInvariant() == "depth.update")
726817
{
727818
var args = token["params"];
@@ -757,17 +848,42 @@ params string[] marketSymbols
757848
{
758849
var id = Interlocked.Increment(ref websocketMessageId);
759850
await _socket.SendMessageAsync(
760-
new
761-
{
762-
id,
763-
method = "depth.subscribe",
764-
@params = marketSymbols
765-
}
766-
);
851+
new
852+
{
853+
id,
854+
method = "depth.subscribe",
855+
@params = marketSymbols
856+
}
857+
);
767858
}
768859
);
769860
}
770861

862+
private static async Task SubscribeToChannel(
863+
IWebSocket socket,
864+
int id,
865+
string channel,
866+
string[] marketSymbols
867+
)
868+
{
869+
if (marketSymbols.Length == 0)
870+
{
871+
marketSymbols = new[] { "all" };
872+
}
873+
874+
var payload = JsonConvert.SerializeObject(
875+
new
876+
{
877+
Id = id,
878+
method = channel,
879+
@params = marketSymbols
880+
},
881+
SerializerSettings
882+
);
883+
884+
await socket.SendMessageAsync(payload);
885+
}
886+
771887
#endregion WebSocket APIs
772888
}
773889

0 commit comments

Comments
 (0)