1
+ using Newtonsoft . Json ;
2
+ using Newtonsoft . Json . Linq ;
1
3
using System ;
2
4
using System . Collections . Generic ;
3
5
using System . Linq ;
4
- using System . Net . Http ;
5
- using System . Text ;
6
6
using System . Threading ;
7
7
using System . Threading . Tasks ;
8
- using Newtonsoft . Json . Linq ;
9
8
10
9
namespace ExchangeSharp
11
10
{
12
11
public partial class ExchangeDigifinexAPI : ExchangeAPI
13
12
{
14
13
private string [ ] Urls =
15
14
{
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
18
17
"openapi.digifinex.xyz" ,
19
- } ;
18
+ } ;
20
19
21
20
private string fastestUrl = null ;
22
21
private int failedUrlCount ;
@@ -85,7 +84,7 @@ protected override async Task OnGetNonceOffset()
85
84
var timeFaster = now - serverDate ;
86
85
timeWindow = "30" ; // max latency of 30s
87
86
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}");
89
88
}
90
89
catch
91
90
{
@@ -169,9 +168,7 @@ private async Task<ExchangeMarket> ParseExchangeMarketAsync(JToken x)
169
168
} ;
170
169
}
171
170
172
- protected internal override async Task <
173
- IEnumerable < ExchangeMarket >
174
- > OnGetMarketSymbolsMetadataAsync ( )
171
+ protected internal override async Task < IEnumerable < ExchangeMarket > > OnGetMarketSymbolsMetadataAsync ( )
175
172
{
176
173
await inited . Task ;
177
174
JToken obj = await MakeJsonRequestAsync < JToken > ( "markets" ) ;
@@ -189,9 +186,8 @@ protected override async Task<IEnumerable<string>> OnGetMarketSymbolsAsync()
189
186
return ( await GetMarketSymbolsMetadataAsync ( ) ) . Select ( x => x . MarketSymbol ) ;
190
187
}
191
188
192
- private async Task < ExchangeTicker > ParseTickerAsync ( JToken x )
189
+ private async Task < ExchangeTicker > ParseTickerAsync ( JToken t , JToken dateStr )
193
190
{
194
- var t = x [ "ticker" ] [ 0 ] ;
195
191
var symbol = t [ "symbol" ] . ToStringUpperInvariant ( ) ;
196
192
var ( baseCurrency , quoteCurrency ) = await ExchangeMarketSymbolToCurrenciesAsync ( symbol ) ;
197
193
@@ -210,16 +206,34 @@ private async Task<ExchangeTicker> ParseTickerAsync(JToken x)
210
206
QuoteCurrencyVolume = t [ "base_vol" ] . ConvertInvariant < decimal > ( ) ,
211
207
BaseCurrencyVolume = t [ "vol" ] . ConvertInvariant < decimal > ( ) ,
212
208
Timestamp = CryptoUtility . UnixTimeStampToDateTimeSeconds (
213
- x [ "date" ] . ConvertInvariant < long > ( )
209
+ //t["date"].ConvertInvariant<long>()
210
+ dateStr . ConvertInvariant < long > ( )
214
211
) ,
215
212
} ,
216
213
} ;
217
214
}
218
215
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
+
219
233
protected override async Task < ExchangeTicker > OnGetTickerAsync ( string marketSymbol )
220
234
{
221
235
JToken obj = await MakeJsonRequestAsync < JToken > ( $ "/ticker?symbol={ marketSymbol } ") ;
222
- return await ParseTickerAsync ( obj ) ;
236
+ return await ParseTickerAsync ( obj [ "ticker" ] [ 0 ] , obj [ "date" ] ) ;
223
237
}
224
238
225
239
protected override async Task < ExchangeOrderBook > OnGetOrderBookAsync (
@@ -388,9 +402,10 @@ protected override async Task<IEnumerable<ExchangeOrderResult>> OnGetOpenOrderDe
388
402
) ;
389
403
}
390
404
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
+ )
394
409
{
395
410
Dictionary < string , object > payload = await GetNoncePayloadAsync ( ) ;
396
411
var url = "/spot/mytrades?limit=500" ;
@@ -443,7 +458,7 @@ protected override async Task<ExchangeOrderResult> OnGetOrderDetailsAsync(
443
458
$ "/spot/order?order_id={ orderId } ",
444
459
payload : payload
445
460
) ;
446
- var x = token [ "data" ] ;
461
+ var x = token [ "data" ] [ 0 ] ;
447
462
return new ExchangeOrderResult
448
463
{
449
464
MarketSymbol = x [ "symbol" ] . ToStringUpperInvariant ( ) ,
@@ -458,7 +473,7 @@ protected override async Task<ExchangeOrderResult> OnGetOrderDetailsAsync(
458
473
AveragePrice = x [ "avg_price" ] . ConvertInvariant < decimal > ( ) ,
459
474
Amount = x [ "amount" ] . ConvertInvariant < decimal > ( ) ,
460
475
AmountFilled = x [ "executed_amount" ] . ConvertInvariant < decimal > ( ) ,
461
- IsBuy = x [ "type" ] . ToStringLowerInvariant ( ) == "buy " ,
476
+ IsBuy = x [ "type" ] . ToStringLowerInvariant ( ) == "buy_market " ,
462
477
Result = ParseOrderStatus ( x [ "status" ] ) ,
463
478
} ;
464
479
}
@@ -563,10 +578,86 @@ protected override async Task OnCancelOrderAsync(
563
578
564
579
#region WebSocket APIs
565
580
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 ,
568
583
params string [ ] marketSymbols
569
584
)
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
+ )
570
661
{
571
662
await inited . Task ;
572
663
if ( callback == null )
@@ -601,12 +692,12 @@ params string[] marketSymbols
601
692
// "id": null
602
693
// }
603
694
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
+ ) ;
610
701
// doesn't send error msgs - just disconnects
611
702
if ( token [ "method" ] . ToStringLowerInvariant ( ) == "trades.update" )
612
703
{
@@ -658,13 +749,13 @@ await callback.Invoke(
658
749
{
659
750
var id = Interlocked . Increment ( ref websocketMessageId ) ;
660
751
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
+ ) ;
668
759
}
669
760
) ;
670
761
}
@@ -716,12 +807,12 @@ params string[] marketSymbols
716
807
// "id": null
717
808
//}
718
809
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
+ ) ;
725
816
if ( token [ "method" ] . ToStringLowerInvariant ( ) == "depth.update" )
726
817
{
727
818
var args = token [ "params" ] ;
@@ -757,17 +848,42 @@ params string[] marketSymbols
757
848
{
758
849
var id = Interlocked . Increment ( ref websocketMessageId ) ;
759
850
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
+ ) ;
767
858
}
768
859
) ;
769
860
}
770
861
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
+
771
887
#endregion WebSocket APIs
772
888
}
773
889
0 commit comments