public void Dispose()
 {
     if (_Scheduler != null)
     {
         _Scheduler.Dispose();
         _Scheduler = null;
     }
     if (_Node != null)
     {
         _Node.Dispose();
         _Node = null;
     }
     foreach (var dispo in _Disposables)
     {
         dispo.Dispose();
     }
     _Disposables.Clear();
     _Evt.Set();
 }
        public void Listen()
        {
            _Evt.Reset();
            _Scheduler = new SingleThreadTaskScheduler();
            ListenerTrace.Info("Connecting to node " + Configuration.Indexer.Node + "...");
            _Node = _Configuration.Indexer.ConnectToNode(true);
            ListenerTrace.Info("Connected");
            ListenerTrace.Info("Handshaking...");
            _Node.VersionHandshake();
            ListenerTrace.Info("Handshaked");
            _Chain = new ConcurrentChain(_Configuration.Indexer.Network);
            ListenerTrace.Info("Fetching headers...");
            _Node.SynchronizeChain(_Chain);
            ListenerTrace.Info("Headers fetched tip " + _Chain.Tip.Height);
            _Indexer = Configuration.Indexer.CreateIndexer();
            ListenerTrace.Info("Indexing indexer chain...");
            _Indexer.IndexChain(_Chain);
            _Node.MessageReceived += node_MessageReceived;
            _Wallets = _Configuration.Indexer.CreateIndexerClient().GetAllWalletRules();

            ListenerTrace.Info("Connecting and handshaking for the sender node...");
            _SenderNode = _Configuration.Indexer.ConnectToNode(false);
            _SenderNode.VersionHandshake();
            _SenderNode.MessageReceived += _SenderNode_MessageReceived;
            ListenerTrace.Info("Sender node handshaked");

            ListenerTrace.Info("Fetching transactions to broadcast...");

            _Disposables.Add(
                Configuration
                .GetBroadcastedTransactionsListenable()
                .CreateConsumer()
                .EnsureExists()
                .OnMessage(evt =>
            {
                uint256 hash = null;
                try
                {
                    if (evt.Addition)
                    {
                        var tx    = new BroadcastedTransaction(evt.AddedEntity);
                        hash      = tx.Transaction.GetHash();
                        var value = _BroadcastedTransactions.GetOrAdd(hash, tx);
                        ListenerTrace.Info("Broadcasting " + hash);
                        if (value == tx)     //Was not present before
                        {
                            _SenderNode.SendMessage(new InvPayload(tx.Transaction));
                        }
                    }
                }
                catch (Exception ex)
                {
                    LastException = ex;
                    ListenerTrace.Error("Error for new broadcasted transaction " + hash, ex);
                }
                finally
                {
                    DeleteExpiredBroadcasted(evt, hash);
                }
            }));
            ListenerTrace.Info("Transactions to broadcast fetched");
            ListenerTrace.Info("Fetching wallet rules...");
            _Disposables.Add(Configuration
                             .GetWalletRuleListenable()
                             .CreateConsumer()
                             .EnsureExists()
                             .OnMessage(evt =>
            {
                ListenerTrace.Info("New wallet rule");
                RunTask("New wallet rule", () =>
                {
                    _Wallets.Add(new WalletRuleEntry(evt.AddedEntity, Configuration.Indexer.CreateIndexerClient()));
                }, true);
            }));
            ListenerTrace.Info("Wallet rules fetched");

            var ping = new Timer(Ping, null, 0, 1000 * 60);

            _Disposables.Add(ping);
        }