public async Task <long> Get(string address, int level) { var account = await Accounts.GetAsync(address); if (account == null || level < account.FirstLevel) { return(0); } if (level >= account.LastLevel) { return(account.Balance); } var to = level - account.FirstLevel < account.LastLevel - level ? level : 0; var from = to == 0 ? level : 0; var union = SumUnion(account, from, to); if (union.Length == 0) { return(0); } var sql = from == 0 ? $@" SELECT SUM(""Change"")::bigint FROM ({union}) as u" : $@" SELECT acc.""Balance"" - COALESCE((SUM(""Change"") OVER ())::bigint, 0) FROM ({union}) as u INNER JOIN ""Accounts"" as acc ON acc.""Id"" = {account.Id}"; using var db = GetConnection(); return(await db.ExecuteScalarAsync <long>(sql, new { account = account.Id, level })); }
public async Task BindModelAsync(ModelBindingContext bindingContext) { var key = bindingContext.HttpContext.Request.Query.Keys.FirstOrDefault(x => x.StartsWith("anyof")); if (key == null) { bindingContext.Result = ModelBindingResult.Success(null); return; } var fields = key.Split(".", StringSplitOptions.RemoveEmptyEntries).Skip(1); if (fields.Count() < 2) { bindingContext.ModelState.TryAddModelError(key, "Invalid syntax of `anyof` parameter. At least two fields must be specified, e.g. `anyof.field1.field2=value`."); return; } var hasValue = false; if (!bindingContext.TryGetAccount(key, ref hasValue, out var value)) { return; } if (!hasValue) { bindingContext.Result = ModelBindingResult.Success(null); return; } bindingContext.Result = ModelBindingResult.Success(new AnyOfParameter { Fields = fields, Value = (await Accounts.GetAsync(value))?.Id ?? -1 }); }
public async Task <IEnumerable <BakingInterval> > GetSchedule(string address, DateTime from, DateTime to, int maxPriority) { var state = State.Current; var proto = Protocols.Current; var rawAccount = await Accounts.GetAsync(address); var fromLevel = from > state.Timestamp ? state.Level + (int)(from - state.Timestamp).TotalSeconds / proto.TimeBetweenBlocks : Time.FindLevel(from, SearchMode.ExactOrHigher); var toLevel = to > state.Timestamp ? state.Level + (int)(to - state.Timestamp).TotalSeconds / proto.TimeBetweenBlocks : Time.FindLevel(to, SearchMode.ExactOrLower); if (!(rawAccount is RawDelegate) || fromLevel == -1 || toLevel == -1) { return(Enumerable.Empty <BakingInterval>()); } var fromCycle = fromLevel < 2 ? 0 : Protocols.FindByLevel(fromLevel).GetCycle(fromLevel); var toCycle = toLevel < 2 ? 0 : Protocols.FindByLevel(toLevel).GetCycle(toLevel); var sql = $@" SELECT ""Level"", ""Slots"", ""Status"" FROM ""BakingRights"" WHERE ""BakerId"" = {rawAccount.Id} AND ""Cycle"" >= {fromCycle} AND ""Cycle"" <= {toCycle} AND ""Level"" >= {fromLevel} AND ""Level"" <= {toLevel} AND NOT(""Status"" = 0 AND ""Priority"" IS NOT NULL AND ""Priority"" > {maxPriority})"; using var db = GetConnection(); var rows = await db.QueryAsync(sql); var count = (int)Math.Ceiling((to - from).TotalHours); var intervals = new List <BakingInterval>(count); for (int i = 0; i < count; i++) { var interval = new BakingInterval(); interval.StartTime = from.AddHours(i); interval.EndTime = interval.StartTime.AddSeconds(3599); intervals.Add(interval); } foreach (var row in rows) { var i = (int)(Time[row.Level] - from).TotalHours; if (i >= intervals.Count) { continue; } if (intervals[i].LastLevel == null || row.Level > intervals[i].LastLevel) { intervals[i].LastLevel = row.Level; } if (intervals[i].FirstLevel == null || row.Level < intervals[i].FirstLevel) { intervals[i].FirstLevel = row.Level; } if (intervals[i].Status == null || row.Status > intervals[i].Status) { intervals[i].Status = row.Status; } if (row.Slots == null) { intervals[i].Blocks++; } else { intervals[i].Slots += row.Slots; } } return(intervals); }
public async Task BindModelAsync(ModelBindingContext bindingContext) { var model = bindingContext.ModelName; var hasValue = false; if (!bindingContext.TryGetAccount($"{model}", ref hasValue, out var value)) { return; } if (!bindingContext.TryGetAccount($"{model}.eq", ref hasValue, out var eq)) { return; } if (!bindingContext.TryGetAccount($"{model}.ne", ref hasValue, out var ne)) { return; } if (!bindingContext.TryGetAccountList($"{model}.in", ref hasValue, out var @in)) { return; } if (!bindingContext.TryGetAccountList($"{model}.ni", ref hasValue, out var ni)) { return; } if (!bindingContext.TryGetString($"{model}.eqx", ref hasValue, out var eqx)) { return; } if (!bindingContext.TryGetString($"{model}.nex", ref hasValue, out var nex)) { return; } if (!bindingContext.TryGetBool($"{model}.null", ref hasValue, out var isNull)) { return; } if (!hasValue) { bindingContext.Result = ModelBindingResult.Success(null); return; } int? _eq = null; int? _ne = null; List <int> _listIn = null; List <int> _listNi = null; if ((value ?? eq) != null) { _eq = (await Accounts.GetAsync(value ?? eq))?.Id ?? -1; } if (ne != null) { _ne = (await Accounts.GetAsync(ne))?.Id ?? -1; } if (@in != null) { _listIn = new List <int>(@in.Count); foreach (var addr in @in) { var acc = await Accounts.GetAsync(addr); if (acc != null) { _listIn.Add(acc.Id); } } } if (ni != null) { _listNi = new List <int>(ni.Count); foreach (var addr in ni) { var acc = await Accounts.GetAsync(addr); if (acc != null) { _listNi.Add(acc.Id); } } } bindingContext.Result = ModelBindingResult.Success(new AccountParameter { Eq = _eq, Ne = _ne, In = _listIn, Ni = _listNi, Eqx = eqx, Nex = nex, Null = isNull }); }
public async Task Write(StreamWriter csv, string address, DateTime from, DateTime to, int limit, string delimiter, string separator) { var account = await Accounts.GetAsync(address); if (account == null) { return; } var sql = new StringBuilder(); if (account.DelegationsCount > 0) { UnionDelegations(sql); } if (account.OriginationsCount > 0) { UnionOriginations(sql); } if (account.TransactionsCount > 0) { UnionTransactions(sql); } if (account.RevealsCount > 0) { UnionReveals(sql); } if (account.MigrationsCount > 0) { UnionMigrations(sql); } if (account is RawUser user) { if (user.Activated == true) { UnionActivations(sql); } if (user.RegisterConstantsCount > 0) { UnionRegisterConstant(sql); } } if (account is RawDelegate delegat) { if (delegat.BlocksCount > 0) { UnionBaking(sql); } if (delegat.EndorsementsCount > 0) { UnionEndorsements(sql); } if (delegat.DoubleBakingCount > 0) { UnionDoubleBaking(sql); } if (delegat.DoubleEndorsingCount > 0) { UnionDoubleEndorsing(sql); } if (delegat.NonceRevelationsCount > 0) { UnionNonceRevelations(sql); } if (delegat.RevelationPenaltiesCount > 0) { UnionRevelationPenalties(sql); } } if (sql.Length == 0) { return; } sql.AppendLine(@"ORDER BY ""Id"""); sql.AppendLine(@"LIMIT @limit"); using var db = GetConnection(); var rows = await db.QueryAsync(sql.ToString(), new { account = account.Id, from, to, limit }); #region write header csv.Write("Block level"); csv.Write(delimiter); csv.Write("Datetime"); csv.Write(delimiter); csv.Write("Operation"); csv.Write(delimiter); if (account is RawDelegate) { csv.Write("Reward"); csv.Write(delimiter); csv.Write("Loss"); csv.Write(delimiter); } csv.Write("Received"); csv.Write(delimiter); csv.Write("From address"); csv.Write(delimiter); csv.Write("Sent"); csv.Write(delimiter); csv.Write("Fee"); csv.Write(delimiter); csv.Write("To address"); csv.Write(delimiter); csv.Write("Explorer link"); csv.Write("\n"); #endregion #region write rows var format = new NumberFormatInfo { NumberDecimalSeparator = separator }; foreach (var row in rows) { csv.Write(row.Level); csv.Write(delimiter); csv.Write(row.Timestamp.ToString("yyyy-MM-dd HH:mm:ss")); csv.Write(delimiter); csv.Write(Operations[row.Type]); csv.Write(delimiter); if (account is RawDelegate) { csv.Write(row.Reward == null ? "" : ((decimal)row.Reward / 1_000_000m).ToString(format)); csv.Write(delimiter); csv.Write(row.Loss == null ? "" : ((decimal) - row.Loss / 1_000_000m).ToString(format)); csv.Write(delimiter); } csv.Write(row.Received == null ? "" : ((decimal)row.Received / 1_000_000m).ToString(format)); csv.Write(delimiter); // WARN: possible NullReferenceException if chain reorgs during request execution (very unlikely) csv.Write(row.From == null ? "" : Accounts.Get(row.From).Address); csv.Write(delimiter); csv.Write(row.Sent == null ? "" : ((decimal) - row.Sent / 1_000_000m).ToString(format)); csv.Write(delimiter); csv.Write(row.Fee == null ? "" : ((decimal) - row.Fee / 1_000_000m).ToString(format)); csv.Write(delimiter); // WARN: possible NullReferenceException if chain reorgs during request execution (very unlikely) csv.Write(row.To == null ? "" : Accounts.Get(row.To).Address); csv.Write(delimiter); csv.Write(row.Nonce != null ? $"https://tzkt.io/{row.OpHash}/{row.Counter}/{row.Nonce}" : row.Counter != null ? $"https://tzkt.io/{row.OpHash}/{row.Counter}" : row.OpHash != null ? $"https://tzkt.io/{row.OpHash}" : ""); csv.Write("\n"); } #endregion csv.Flush(); }
public async Task Test(string address) { var account = await Accounts.GetAsync(address); if (account == null) { return; } var sql = new StringBuilder(); if (account.DelegationsCount > 0) { UnionDelegations(sql); } if (account.OriginationsCount > 0) { UnionOriginations(sql); } if (account.TransactionsCount > 0) { UnionTransactions(sql); } if (account.RevealsCount > 0) { UnionReveals(sql); } if (account.MigrationsCount > 0) { UnionMigrations(sql); } if (account is RawUser user) { if (user.Activated == true) { UnionActivations(sql); } } if (account is RawDelegate delegat) { if (delegat.BlocksCount > 0) { UnionBaking(sql); } if (delegat.EndorsementsCount > 0) { UnionEndorsements(sql); } if (delegat.DoubleBakingCount > 0) { UnionDoubleBaking(sql); } if (delegat.DoubleEndorsingCount > 0) { UnionDoubleEndorsing(sql); } if (delegat.NonceRevelationsCount > 0) { UnionNonceRevelations(sql); } if (delegat.RevelationPenaltiesCount > 0) { UnionRevelationPenalties(sql); } } if (sql.Length == 0) { return; } sql.AppendLine(@"ORDER BY ""Id"""); sql.AppendLine(@"LIMIT @limit"); using var db = GetConnection(); var rows = await db.QueryAsync(sql.ToString(), new { account = account.Id, from = DateTime.MinValue, to = DateTime.MaxValue, limit = 10000000 }); var balance = 0m; #region write rows foreach (var row in rows) { if (row.Reward + row.Loss + row.Received + row.Sent + row.Fee == 0) { throw new Exception($"{account.Address}: {row.Id} is empty"); } balance += row.Reward / 1000000m; balance -= row.Loss / 1000000m; balance += row.Received / 1000000m; balance -= row.Sent / 1000000m; balance -= row.Fee / 1000000m; } #endregion if (balance * 1000000 != account.Balance) { Console.WriteLine($"{account.Address}: {account.Balance} != {balance}"); throw new Exception($"{account.Address}: {account.Balance} != {balance}"); } }