Example #1
0
        public async Task <IWalletBalance> UpdateBalance(string address)
        {
            var wallet = await _observableWalletRepository.Get(address);

            if (wallet != null)
            {
                return(await UpdateBalance(wallet));
            }

            return(null);
        }
        public async Task <decimal?> UpdateBalance(string address)
        {
            if (await _observableWalletRepository.Get(address) != null)
            {
                var lastBlock = await _blockchainProvider.GetHeightAsync();

                var unspentOutputs = (await _transactionOutputsService.GetUnspentOutputsAsync(address))
                                     .ToList();

                var blockHeightFromTxHash = new ConcurrentDictionary <UInt256,
                                                                      (string txHash, int blockHeight, string blockHash)>();

                await unspentOutputs.Select(p => p.Reference.PrevHash).Distinct()
                .ForEachAsyncSemaphore(8, async txHash =>
                {
                    var tx = await _blockchainProvider.GetTransactionOrDefaultAsync(txHash.ToString().Substring(2));

                    if (tx == null)
                    {
                        throw new InvalidOperationException($"Unable to find transaction with hash {txHash}");
                    }

                    blockHeightFromTxHash.TryAdd(txHash, tx.Value);
                });

                var validatedUnspentOutputs = unspentOutputs
                                              .Where(p =>
                {
                    var tx = blockHeightFromTxHash[p.Reference.PrevHash];

                    if (tx.blockHash == null)     // unconfirmed tx
                    {
                        return(false);
                    }

                    return(tx.blockHeight <= lastBlock);
                }).ToList();


                var neoBalance = (decimal)validatedUnspentOutputs
                                 .Where(p => p.Output.AssetId == Utils.NeoToken)
                                 .Sum(p => p.Output.Value);

                var gasBalance = (decimal)validatedUnspentOutputs
                                 .Where(p => p.Output.AssetId == Utils.GasToken)
                                 .Sum(p => p.Output.Value);

                await Task.WhenAll(UpdateBalanceInRepo(lastBlock, address, neoBalance, Constants.Assets.Neo.AssetId),
                                   UpdateBalanceInRepo(lastBlock, address, gasBalance, Constants.Assets.Gas.AssetId));;
            }

            return(null);
        }