public async Task <GetTransactionsResponse> GetTransactions( string cryptoCode, [ModelBinder(BinderType = typeof(DestinationModelBinder))] DerivationStrategyBase extPubKey, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> unconfirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> confirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> replacedBookmarks = null, bool includeTransaction = true, bool longPolling = false) { if (extPubKey == null) { throw new ArgumentNullException(nameof(extPubKey)); } var network = GetNetwork(cryptoCode); var chain = ChainProvider.GetChain(network); var repo = RepositoryProvider.GetRepository(network); var waitingTransaction = longPolling ? WaitingTransaction(extPubKey) : Task.FromResult(false); GetTransactionsResponse response = null; while (true) { response = new GetTransactionsResponse(); int currentHeight = chain.Height; response.Height = currentHeight; var txs = GetAnnotatedTransactions(repo, chain, extPubKey); foreach (var item in new[] { new { TxSet = response.ConfirmedTransactions, KnownBookmarks = confirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ConfirmedTransactions }, new { TxSet = response.UnconfirmedTransactions, KnownBookmarks = unconfirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.UnconfirmedTransactions }, new { TxSet = response.ReplacedTransactions, KnownBookmarks = replacedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ReplacedTransactions }, }) { item.TxSet.Bookmark = Bookmark.Start; item.TxSet.KnownBookmark = item.KnownBookmarks.Contains(Bookmark.Start) ? Bookmark.Start : null; BookmarkProcessor processor = new BookmarkProcessor(32 + 32 + 25); foreach (var tx in item.AnnotatedTx.Values) { processor.PushNew(); processor.AddData(tx.Record.Transaction.GetHash()); processor.AddData(tx.Record.BlockHash ?? uint256.Zero); processor.UpdateBookmark(); var txInfo = new TransactionInformation() { BlockHash = tx.Record.BlockHash, Height = tx.Record.BlockHash == null ? null : tx.Height, TransactionId = tx.Record.Transaction.GetHash(), Transaction = includeTransaction ? tx.Record.Transaction : null, Confirmations = tx.Record.BlockHash == null ? 0 : currentHeight - tx.Height.Value + 1, Timestamp = txs.GetByTxId(tx.Record.Transaction.GetHash()).Select(t => t.Record.FirstSeen).First(), Inputs = ToMatch(txs, tx.Record.Transaction.Inputs.Select(o => txs.GetUTXO(o.PrevOut)).ToList(), extPubKey, tx.Record.TransactionMatch.Inputs), Outputs = ToMatch(txs, tx.Record.Transaction.Outputs, extPubKey, tx.Record.TransactionMatch.Outputs) }; item.TxSet.Transactions.Add(txInfo); txInfo.BalanceChange = txInfo.Outputs.Select(o => o.Value).Sum() - txInfo.Inputs.Select(o => o.Value).Sum(); item.TxSet.Bookmark = processor.CurrentBookmark; if (item.KnownBookmarks.Contains(processor.CurrentBookmark)) { item.TxSet.KnownBookmark = processor.CurrentBookmark; item.TxSet.Transactions.Clear(); } } } if (response.HasChanges() || !(await waitingTransaction)) { break; } waitingTransaction = Task.FromResult(false); //next time, will not wait } return(response); }
public async Task <GetTransactionsResponse> GetTransactions( string cryptoCode, [ModelBinder(BinderType = typeof(DerivationStrategyModelBinder))] DerivationStrategyBase derivationScheme, [ModelBinder(BinderType = typeof(BitcoinAddressModelBinder))] BitcoinAddress address, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> unconfirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> confirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> replacedBookmarks = null, bool includeTransaction = true, bool longPolling = false) { var trackedSource = GetTrackedSource(derivationScheme, address); if (trackedSource == null) { throw new ArgumentNullException(nameof(trackedSource)); } GetTransactionsResponse response = null; using (CancellationTokenSource cts = new CancellationTokenSource()) { if (longPolling) { cts.CancelAfter(LongPollTimeout); } var network = GetNetwork(cryptoCode, false); var chain = ChainProvider.GetChain(network); var repo = RepositoryProvider.GetRepository(network); while (true) { response = new GetTransactionsResponse(); int currentHeight = chain.Height; response.Height = currentHeight; var txs = await GetAnnotatedTransactions(repo, chain, trackedSource); foreach (var item in new[] { new { TxSet = response.ConfirmedTransactions, KnownBookmarks = confirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ConfirmedTransactions }, new { TxSet = response.UnconfirmedTransactions, KnownBookmarks = unconfirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.UnconfirmedTransactions }, new { TxSet = response.ReplacedTransactions, KnownBookmarks = replacedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ReplacedTransactions }, }) { item.TxSet.Bookmark = Bookmark.Start; item.TxSet.KnownBookmark = item.KnownBookmarks.Contains(Bookmark.Start) ? Bookmark.Start : null; BookmarkProcessor processor = new BookmarkProcessor(32 + 32 + 25); foreach (var tx in item.AnnotatedTx) { processor.PushNew(); processor.AddData(tx.Record.TransactionHash); processor.AddData(tx.Record.BlockHash ?? uint256.Zero); processor.UpdateBookmark(); var txInfo = new TransactionInformation() { BlockHash = tx.Height.HasValue ? tx.Record.BlockHash : null, Height = tx.Height, TransactionId = tx.Record.TransactionHash, Transaction = includeTransaction ? tx.Record.Transaction : null, Confirmations = tx.Height.HasValue ? currentHeight - tx.Height.Value + 1 : 0, Timestamp = txs.GetByTxId(tx.Record.TransactionHash).Select(t => t.Record.FirstSeen).First(), Inputs = tx.Record.SpentOutpoints.Select(o => txs.GetUTXO(o)).Where(o => o != null).ToList(), Outputs = tx.Record.GetReceivedOutputs(trackedSource).ToList() }; item.TxSet.Transactions.Add(txInfo); txInfo.BalanceChange = txInfo.Outputs.Select(o => o.Value).Sum() - txInfo.Inputs.Select(o => o.Value).Sum(); item.TxSet.Bookmark = processor.CurrentBookmark; if (item.KnownBookmarks.Contains(processor.CurrentBookmark)) { item.TxSet.KnownBookmark = processor.CurrentBookmark; item.TxSet.Transactions.Clear(); } } } if (!longPolling || response.HasChanges()) { break; } if (!await WaitingTransaction(trackedSource, cts.Token)) { break; } } } return(response); }