private IEnumerable <SyncTransactionAddressItem> SelectAddressWithPool(SyncBlockInfo current, string address, bool availableOnly) { FilterDefinitionBuilder <MapTransactionAddress> builder = Builders <MapTransactionAddress> .Filter; var addressFiler = new List <string> { address }; FilterDefinition <MapTransactionAddress> filter = builder.AnyIn(transactionAddress => transactionAddress.Addresses, addressFiler); if (availableOnly) { // we only want spendable transactions filter = filter & builder.Eq(info => info.SpendingTransactionId, null); } watch.Restart(); SortDefinition <MapTransactionAddress> sort = Builders <MapTransactionAddress> .Sort.Descending(info => info.BlockIndex); var addrs = MapTransactionAddress.Find(filter).Sort(sort).ToList(); watch.Stop(); log.LogInformation($"Select: Seconds = {watch.Elapsed.TotalSeconds} - UnspentOnly = {availableOnly} - Addr = {address} - Items = {addrs.Count()}"); // this creates a copy of the collection (to avoid thread issues) ICollection <Transaction> pool = MemoryTransactions.Values; if (pool.Any()) { // mark trx in output as spent if they exist in the pool List <MapTransactionAddress> addrsupdate = addrs; GetPoolOutputs(pool).ForEach(f => { MapTransactionAddress adr = addrsupdate.FirstOrDefault(a => a.TransactionId == f.Item1.PrevOut.Hash.ToString() && a.Index == f.Item1.PrevOut.N); if (adr != null) { adr.SpendingTransactionId = f.Item2; } }); // if only spendable transactions are to be returned we need to remove // any that have been marked as spent by a transaction in the pool if (availableOnly) { addrs = addrs.Where(d => d.SpendingTransactionId == null).ToList(); } // add all pool transactions to main output var paddr = PoolToMapTransactionAddress(pool, address).ToList(); addrs = addrs.OrderByDescending(s => s.BlockIndex).Concat(paddr).ToList(); } // map to return type and calculate confirmations return(addrs.Select(s => new SyncTransactionAddressItem { Address = address, Index = s.Index, TransactionHash = s.TransactionId, BlockIndex = s.BlockIndex == -1 ? default(long?) : s.BlockIndex, Value = s.Value, Confirmations = s.BlockIndex == -1 ? 0 : current.BlockIndex - s.BlockIndex + 1, SpendingTransactionHash = s.SpendingTransactionId, SpendingBlockIndex = s.SpendingBlockIndex, CoinBase = s.CoinBase, CoinStake = s.CoinStake, ScriptHex = new Script(Encoders.Hex.DecodeData(s.ScriptHex)).ToString(), Type = StandardScripts.GetTemplateFromScriptPubKey(new Script(Encoders.Hex.DecodeData(s.ScriptHex)))?.Type.ToString(), Time = s.BlockIndex == -1 ? UnixUtils.DateToUnixTimestamp(DateTime.UtcNow) : current.BlockTime })); }
public string GetSpendingTransaction(string transaction, int index) { FilterDefinition <MapTransactionAddress> filter = Builders <MapTransactionAddress> .Filter.Eq(addr => addr.Id, string.Format("{0}-{1}", transaction, index)); return(MapTransactionAddress.Find(filter).ToList().Select(t => t.SpendingTransactionId).FirstOrDefault()); }