async void ProcessLiveOrderMessage(JObject jobj)
        {
            dynamic m = jobj;

            if ((decimal)m.sequence != 1m + _lastSequenceNumber)
            {
                await BuildBookAsync();

                return;
            }

            BookUpdateReceived?.Invoke(this, new GdaxWebSocketMessageEventArgs(jobj));

            _lastSequenceNumber = m.sequence;

            string type = m.type;

            switch (type)
            {
            case "received":
                ProcessReceivedMessage(jobj);
                break;

            case "open":
                ProcessOpenMessage(jobj);
                break;

            case "done":
                ProcessDoneMessage(jobj);
                break;

            case "match":
                ProcessMatchMessage(jobj);
                break;

            case "change":
                ProcessChangeMessage(jobj);
                break;

            case "error":
                ProcessErrorMessage(jobj);
                break;

            default:
                return;
            }

            var newInsideMarket = new InsideMarket(_bids.GetBest(), _asks.GetBest());

            if (!_insideMarket.Equals(newInsideMarket))
            {
                var args = new InsideMarketChangedEventArgs(_instrument, newInsideMarket, _insideMarket);
                _insideMarket = newInsideMarket;

                InsideMarketChanged?.Invoke(this, args);
            }
        }
        public void Start()
        {
            if (Interlocked.CompareExchange(ref _keepRunning, 1, 0) == 0)
            {
                _workerThread = new Thread(() =>
                {
                    while (_keepRunning != 0)
                    {
                        try
                        {
                            var json = _client.GetLevel1Book(_instrument.Symbol).Result;

                            InsideMarket oldInsideMarket = _insideMarket;

                            _insideMarket = new InsideMarket(GetPriceSize(json, "bids"),
                                                             GetPriceSize(json, "asks"));

                            if (!oldInsideMarket.Equals(_insideMarket))
                            {
                                InsideMarketChanged?.Invoke(
                                    this,
                                    new InsideMarketChangedEventArgs(_instrument, oldInsideMarket, _insideMarket));
                            }

                            Thread.Sleep(_timeout);
                        }
                        catch (Exception ex)
                        {
                            // ignore for now
                            Console.WriteLine(ex.Message);
                        }
                    }
                });
                _workerThread.Start();
            }
        }