/// <summary> Updates this object. </summary> /// /// <remarks> Paul, 05/02/2015. </remarks> async public override void Update() { try { // // don't process transactions if the network is in danger // GetInfoResponse info = m_bitshares.GetInfo(); m_suspended = info.blockchain_average_delegate_participation < kMinDelegateParticipation; if (!m_suspended) { Dictionary <string, MarketRow> allMarkets = GetAllMarkets().ToDictionary(m => m.symbol_pair); m_allCurrencies = m_dataAccess.GetAllCurrencies(); // create any handlers we need for new markets CheckMarketHandlers(allMarkets); // get all markets RecomputeTransactionLimitsAndPrices(allMarkets); // // handle bitshares->bitcoin // Dictionary <string, BitsharesLedgerEntry> bitsharesDeposits = HandleBitsharesDesposits(); // // handle bitcoin->bitshares // List <TransactionSinceBlock> bitcoinDeposits = HandleBitcoinDeposits(); // // process bitshares deposits // uint siteLastTid = m_dataAccess.GetSiteLastTransactionUid(); foreach (KeyValuePair <string, BitsharesLedgerEntry> kvpDeposit in bitsharesDeposits) { // figure out which market each deposit belongs to foreach (KeyValuePair <string, MarketBase> kvpHandler in m_marketHandlers) { BitsharesLedgerEntry l = kvpDeposit.Value; MarketRow m = allMarkets[kvpHandler.Key]; BitsharesAsset depositAsset = m_allBitsharesAssets[l.amount.asset_id]; if (!HandleCommand(l, kvpHandler.Value, m, kvpDeposit.Key)) { if (IsDepositForMarket(l.memo, m.symbol_pair)) { // make sure the deposit is for this market! if (kvpHandler.Value.CanDepositAsset(CurrencyHelpers.FromBitsharesSymbol(depositAsset.symbol, m_allCurrencies, depositAsset.IsUia()))) { kvpHandler.Value.HandleBitsharesDeposit(kvpDeposit); } } } } // this needs to happen for every transaction RecomputeTransactionLimitsAndPrices(allMarkets); } // // process bitcoin deposits // List <TransactionsRow> pendingTransactions = m_dataAccess.GetAllPendingTransactions(); foreach (TransactionSinceBlock deposit in bitcoinDeposits) { // figure out which market each deposit belongs to foreach (KeyValuePair <string, MarketBase> kvpHandler in m_marketHandlers) { if (IsDepositForMarket(deposit.Address, allMarkets[kvpHandler.Key].symbol_pair)) { kvpHandler.Value.HandleBitcoinDeposit(deposit); } } // this needs to happen for every transaction RecomputeTransactionLimitsAndPrices(allMarkets); } // // handle changes in transaction status // List <TransactionsRow> updatedTrans = new List <TransactionsRow>(); foreach (TransactionsRow pending in pendingTransactions) { TransactionsRow updated = m_dataAccess.GetTransaction(pending.received_txid); if (updated.status != MetaOrderStatus.pending) { updatedTrans.Add(updated); } } // // push any new transactions, make sure site acknowledges receipt // uint latestTid = m_dataAccess.GetLastTransactionUid(); if (latestTid > siteLastTid || updatedTrans.Count > 0) { List <TransactionsRow> newTrans = m_dataAccess.GetAllTransactionsSince(siteLastTid); // lump them together newTrans.AddRange(updatedTrans); // send 'em all string result = await ApiPush <List <TransactionsRow> >(Routes.kPushTransactions, newTrans); if (bool.Parse(result)) { m_dataAccess.UpdateSiteLastTransactionUid(latestTid); } else { throw new Exception("API push response unknown! " + result); } } // // push market updates // foreach (KeyValuePair <string, MarketBase> kvpHandler in m_marketHandlers) { if (kvpHandler.Value.m_IsDirty) { m_dataAccess.UpdateMarketInDatabase(kvpHandler.Value.m_Market); #pragma warning disable 4014 ApiPush <MarketRow>(Routes.kPushMarket, kvpHandler.Value.m_Market); #pragma warning restore 4014 kvpHandler.Value.m_IsDirty = false; } } // // push fee collections // if (m_bitcoinFeeAddress != null && m_bitshaaresFeeAccount != null) { uint lastFeeId = m_dataAccess.GetSiteLastFeeUid(); // collect our fees foreach (KeyValuePair <string, MarketBase> kvpHandler in m_marketHandlers) { kvpHandler.Value.CollectFees(m_bitcoinFeeAddress, m_bitshaaresFeeAccount); } // keep the site up to date, make sure it acknowledges receipt uint latestFeeId = m_dataAccess.GetLastFeeCollectionUid(); if (latestFeeId > lastFeeId) { List <FeeCollectionRow> fees = m_dataAccess.GetFeeCollectionsSince(lastFeeId); string result = await ApiPush <List <FeeCollectionRow> >(Routes.kPushFees, fees); if (bool.Parse(result)) { m_dataAccess.UpdateSiteLastFeeUid(latestFeeId); } else { throw new Exception("API push response unknown! " + result); } } } } // // wait for a stop command to exit gracefully // if (m_lastCommand == null) { m_lastCommand = ReadConsoleAsync(); string command = await m_lastCommand; // remember we never get here unless a command was entered Console.WriteLine("got command: " + command); if (command == "stop") { m_scheduler.Dispose(); } m_lastCommand = null; } } catch (UnsupportedTransactionException ute) { // ignore so we can move on! m_dataAccess.IgnoreTransaction(ute.m_trxId); // log it LogGeneralException(ute.ToString()); } catch (Exception e) { LogGeneralException(e.ToString()); } }