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); }
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); }
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)); }
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); }
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); }
public BalanceSummary() { Confirmed = new BalanceSummaryDetails(); }