Beispiel #1
0
        private Money SelectAmount(AssetId asset, BalanceSummaryDetails balanceSummaryDetails)
        {
            if (asset == null)
            {
                return(balanceSummaryDetails.Amount);
            }
            var assetDetails = balanceSummaryDetails.Assets.FirstOrDefault(a => a.Asset.AssetId == asset);

            if (assetDetails == null)
            {
                return(Money.Zero);
            }
            return(assetDetails.Quantity);
        }
Beispiel #2
0
        public static BalanceSummaryDetails operator -(BalanceSummaryDetails c1)
        {
            if (c1 == null)
            {
                return(null);
            }
            BalanceSummaryDetails result = new BalanceSummaryDetails
            {
                Amount           = -c1.Amount,
                Received         = -c1.Received,
                TransactionCount = -c1.TransactionCount,
                Assets           = Minus(c1.Assets)
            };

            return(result);
        }
Beispiel #3
0
        private IMoney SelectAmount(IMoney zero, BalanceSummaryDetails balanceSummaryDetails)
        {
            var cc = zero as AssetMoney;

            if (cc == null)
            {
                return(balanceSummaryDetails.Amount);
            }
            var assetDetails = balanceSummaryDetails.Assets.FirstOrDefault(a => a.Asset.AssetId == cc.Id);

            if (assetDetails == null)
            {
                return(zero);
            }
            return(new AssetMoney(assetDetails.Asset, assetDetails.Quantity));
        }
Beispiel #4
0
        internal static BalanceSummaryDetails CreateFrom(List <OrderedBalanceChange> changes, Network network, bool colored)
        {
            var details = new BalanceSummaryDetails
            {
                Amount           = CalculateAmount(changes),
                TransactionCount = changes.Count,
                Received         = changes.Select(_ => _.Amount < Money.Zero ? Money.Zero : _.Amount).Sum(),
            };

            if (colored)
            {
                Dictionary <AssetId, AssetBalanceSummaryDetails> coloredDetails = new Dictionary <AssetId, AssetBalanceSummaryDetails>();
                foreach (var change in changes)
                {
                    foreach (var coin in change.ReceivedCoins.OfType <ColoredCoin>())
                    {
                        AssetBalanceSummaryDetails coloredDetail = null;
                        if (!coloredDetails.TryGetValue(coin.AssetId, out coloredDetail))
                        {
                            coloredDetail       = new AssetBalanceSummaryDetails();
                            coloredDetail.Asset = coin.AssetId.GetWif(network);
                            coloredDetails.Add(coin.AssetId, coloredDetail);
                        }
                        coloredDetail.Quantity += (long)coin.Amount.Quantity;
                        coloredDetail.Received += (long)coin.Amount.Quantity;
                    }
                    foreach (var coin in change.SpentCoins.OfType <ColoredCoin>())
                    {
                        AssetBalanceSummaryDetails coloredDetail = null;
                        if (!coloredDetails.TryGetValue(coin.AssetId, out coloredDetail))
                        {
                            coloredDetail       = new AssetBalanceSummaryDetails();
                            coloredDetail.Asset = coin.AssetId.GetWif(network);
                            coloredDetails.Add(coin.AssetId, coloredDetail);
                        }
                        coloredDetail.Quantity -= (long)coin.Amount.Quantity;
                    }
                }
                details.Assets = coloredDetails.Values.ToArray();
            }
            return(details);
        }
Beispiel #5
0
        public BalanceSummary BalanceSummary(
            BalanceId balanceId,
            BlockFeature at,
            bool debug,
            bool colored,
            int?unconfExpiration)
        {
            var expiration = GetExpiration(unconfExpiration);
            var repo       = Configuration.CreateWalletRepository();
            CancellationTokenSource cancel = new CancellationTokenSource();

            cancel.CancelAfter(30000);
            var checkpoint = Configuration.Indexer.CreateIndexer()
                             .GetCheckpoint(balanceId.Type == BalanceType.Address ? IndexerCheckpoints.Balances : IndexerCheckpoints.Wallets);

            var atBlock = AtBlock(at);

            var query = new BalanceQuery();

            query.RawOrdering = true;
            query.From        = null;

            if (at != null)
            {
                query.From = ToBalanceLocator(atBlock);
            }
            if (query.From == null)
            {
                query.From = new UnconfirmedBalanceLocator(DateTimeOffset.UtcNow - expiration);
            }

            query.PageSizes = new[] { 1, 10, 100 };

            var cacheTable    = repo.GetBalanceSummaryCacheTable(balanceId, colored);
            var cachedSummary = cacheTable.Query(Chain, query).FirstOrDefault(c => (((ConfirmedBalanceLocator)c.Locator).BlockHash == atBlock.HashBlock && at != null) ||
                                                                              c.Immature.TransactionCount == 0 ||
                                                                              ((c.Immature.TransactionCount != 0) && !IsMature(c.OlderImmature, atBlock)));

            var cachedLocator = cachedSummary == null ? null : (ConfirmedBalanceLocator)cachedSummary.Locator;

            if (cachedSummary != null && at != null && cachedLocator.Height == atBlock.Height)
            {
                cachedSummary.CacheHit = CacheHit.FullCache;
                cachedSummary.PrepareForSend(at, debug);
                return(cachedSummary);
            }

            cachedSummary = cachedSummary ?? new BalanceSummary()
            {
                Confirmed     = new BalanceSummaryDetails(),
                UnConfirmed   = new BalanceSummaryDetails(),
                OlderImmature = int.MaxValue
            };

            int stopAtHeight = cachedSummary.Locator == null ? -1 : cachedLocator.Height;
            int lookback     = (int)(expiration.Ticks / this.Network.Consensus.PowTargetSpacing.Ticks);

            if (at == null)
            {
                stopAtHeight = stopAtHeight - lookback;
            }

            var client = Configuration.Indexer.CreateIndexerClient();

            client.ColoredBalance = colored;

            var diff =
                client
                .GetOrderedBalance(balanceId, query)
                .WhereNotExpired(expiration)
                .TakeWhile(_ => !cancel.IsCancellationRequested)
                //Some confirmation of the fetched unconfirmed may hide behind stopAtHeigh
                .TakeWhile(_ => _.BlockId == null || _.Height > stopAtHeight - lookback)
                .AsBalanceSheet(Chain);

            if (cancel.Token.IsCancellationRequested)
            {
                throw new HttpResponseException(new HttpResponseMessage()
                {
                    StatusCode   = HttpStatusCode.InternalServerError,
                    ReasonPhrase = "The server can't fetch the balance summary because the balance is too big. Please, load it in several step with ?at={blockFeature} parameter. Once fully loaded after all the step, the summary will return in constant time."
                });
            }
            RemoveBehind(diff, stopAtHeight);
            RemoveConflicts(diff);

            var unconfs = diff.Unconfirmed;
            var confs   = cachedLocator == null ?
                          diff.Confirmed :
                          diff.Confirmed.Where(c => c.Height > cachedLocator.Height).ToList();

            var immature = confs.Where(c => !IsMature(c, atBlock)).ToList();


            var summary = new BalanceSummary()
            {
                Confirmed   = BalanceSummaryDetails.CreateFrom(confs, Network, colored),
                Immature    = BalanceSummaryDetails.CreateFrom(immature, Network, colored),
                UnConfirmed = BalanceSummaryDetails.CreateFrom(unconfs, Network, colored),
            };

            summary.Confirmed += cachedSummary.Confirmed;
            summary.Immature  += cachedSummary.Immature;
            summary.Locator    = new ConfirmedBalanceLocator(atBlock.Height, atBlock.HashBlock);
            summary.CacheHit   = cachedSummary.Locator == null ? CacheHit.NoCache : CacheHit.PartialCache;

            var newCachedLocator = (ConfirmedBalanceLocator)summary.Locator;

            if (
                cachedSummary.Locator == null ||
                newCachedLocator.BlockHash != cachedLocator.BlockHash)
            {
                var olderImmature    = immature.Select(_ => _.Height).Concat(new[] { int.MaxValue }).Min();
                var newCachedSummary = new Models.BalanceSummary()
                {
                    Confirmed     = summary.Confirmed,
                    Immature      = summary.Immature,
                    Locator       = summary.Locator,
                    OlderImmature = Math.Min(cachedSummary.OlderImmature, olderImmature)
                };
                var checkpointBlock = Chain.GetBlock(checkpoint.BlockLocator.Blocks[0]);
                if (checkpointBlock != null && checkpointBlock.Height >= atBlock.Height)
                {
                    cacheTable.Create(newCachedLocator, newCachedSummary);
                }
            }

            summary.PrepareForSend(at, debug);
            return(summary);
        }
Beispiel #6
0
 public BalanceSummary()
 {
     Confirmed = new BalanceSummaryDetails();
 }