1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33using System . Linq ;
44using System . Threading . Tasks ;
55using ExchangeSharp . Models ;
6+ using Newtonsoft . Json ;
67using Newtonsoft . Json . Linq ;
8+ using ExchangeSharp . API . Exchanges . MEXC . Models ;
79
810namespace ExchangeSharp
911{
@@ -21,6 +23,7 @@ private ExchangeMEXCAPI()
2123 MarketSymbolSeparator = string . Empty ;
2224 MarketSymbolIsUppercase = true ;
2325 RateLimit = new RateGate ( 20 , TimeSpan . FromSeconds ( 2 ) ) ;
26+ WebSocketOrderBookType = WebSocketOrderBookType . FullBookFirstThenDeltas ;
2427 }
2528
2629 public override Task < string > ExchangeMarketSymbolToGlobalMarketSymbolAsync ( string marketSymbol )
@@ -369,6 +372,110 @@ protected override async Task OnCancelOrderAsync(string orderId, string marketSy
369372 await MakeJsonRequestAsync < JToken > ( "/order" , BaseUrl , payload , "DELETE" ) ;
370373 }
371374
375+ protected override async Task < IWebSocket > OnGetDeltaOrderBookWebSocketAsync (
376+ Action < ExchangeOrderBook > callback ,
377+ int maxCount = 20 ,
378+ params string [ ] marketSymbols
379+ )
380+ {
381+ if ( marketSymbols == null || marketSymbols . Length == 0 )
382+ {
383+ marketSymbols = ( await GetMarketSymbolsAsync ( ) ) . ToArray ( ) ;
384+ }
385+
386+ var initialSequenceIds = new Dictionary < string , long > ( ) ;
387+
388+ return await ConnectPublicWebSocketAsync (
389+ string . Empty ,
390+ ( _socket , msg ) =>
391+ {
392+ var json = msg . ToStringFromUTF8 ( ) ;
393+
394+ MarketDepthDiffUpdate update = null ;
395+ try
396+ {
397+ update = JsonConvert . DeserializeObject < MarketDepthDiffUpdate > ( json , SerializerSettings ) ;
398+ }
399+ catch
400+ {
401+ }
402+
403+ if ( update == null || string . IsNullOrWhiteSpace ( update . Channel ) || update . Details == null )
404+ {
405+ return Task . CompletedTask ;
406+ }
407+
408+ if ( update . Details . Version < initialSequenceIds [ update . Symbol ] )
409+ {
410+ // A deprecated update should be ignored
411+ return Task . CompletedTask ;
412+ }
413+
414+ var eventTimeDateTime = update . EventTime . UnixTimeStampToDateTimeMilliseconds ( ) ;
415+
416+ var orderBook = new ExchangeOrderBook
417+ {
418+ IsFromSnapshot = false ,
419+ ExchangeName = Name ,
420+ SequenceId = update . Details . Version ,
421+ MarketSymbol = update . Symbol ,
422+ LastUpdatedUtc = eventTimeDateTime ,
423+ } ;
424+
425+ if ( update . Details . Asks != null )
426+ {
427+ foreach ( var ask in update . Details . Asks )
428+ {
429+ orderBook . Asks [ ask . Price ] = new ExchangeOrderPrice
430+ {
431+ Price = ask . Price ,
432+ Amount = ask . Volume ,
433+ } ;
434+ }
435+ }
436+
437+ if ( update . Details . Bids != null )
438+ {
439+ foreach ( var bid in update . Details . Bids )
440+ {
441+ orderBook . Bids [ bid . Price ] = new ExchangeOrderPrice
442+ {
443+ Price = bid . Price ,
444+ Amount = bid . Volume ,
445+ } ;
446+ }
447+ }
448+
449+ callback ( orderBook ) ;
450+
451+ return Task . CompletedTask ;
452+ } ,
453+ async ( _socket ) =>
454+ {
455+ foreach ( var marketSymbol in marketSymbols ) // "Every websocket connection maximum support 30 subscriptions at one time." - API docs
456+ {
457+ var initialBook = await OnGetOrderBookAsync ( marketSymbol , maxCount ) ;
458+ initialBook . IsFromSnapshot = true ;
459+
460+ callback ( initialBook ) ;
461+
462+ initialSequenceIds [ marketSymbol ] = initialBook . SequenceId ;
463+
464+ var subscriptionParams = new List < string >
465+ {
466+ $ "[email protected] @{ marketSymbol } " 467+ } ;
468+
469+ await _socket . SendMessageAsync ( new WebSocketSubscription
470+ {
471+ Method = "SUBSCRIPTION" ,
472+ Params = subscriptionParams ,
473+ } ) ;
474+ }
475+ }
476+ ) ;
477+ }
478+
372479 private async Task < JToken > GetBalance ( )
373480 {
374481 var token = await MakeJsonRequestAsync < JToken > ( "/account" , payload : await GetNoncePayloadAsync ( ) ) ;
0 commit comments