From d04bfd5f30ea117dd5a75b0b9eb1d53a1e1087a6 Mon Sep 17 00:00:00 2001 From: Groxan <257byte@gmail.com> Date: Thu, 25 Feb 2021 18:17:45 +0300 Subject: [PATCH] Add .gt, .ge, .lt, .le modes to JsonParameter and minor refactoring --- Tzkt.Api/Controllers/AccountsController.cs | 10 +- Tzkt.Api/Controllers/ContractsController.cs | 4 +- Tzkt.Api/Controllers/OperationsController.cs | 18 +- Tzkt.Api/Models/Entrypoint.cs | 3 +- .../Models/Operations/TransactionOperation.cs | 24 ++- Tzkt.Api/Models/StorageRecord.cs | 81 ++------ Tzkt.Api/Parameters/Binders/JsonBinder.cs | 44 ++++ Tzkt.Api/Parameters/JsonParameter.cs | 58 +++++- Tzkt.Api/Repositories/AccountRepository.cs | 58 +++--- Tzkt.Api/Repositories/OperationRepository.cs | 189 ++++++++++-------- Tzkt.Api/Utils/Converters/RawJsonConverter.cs | 20 -- Tzkt.Api/Utils/JsonString.cs | 30 +++ Tzkt.Api/Utils/SqlBuilder.cs | 53 +++++ Tzkt.Api/Utils/StringAsJson.cs | 27 --- .../Commits/Operations/TransactionsCommit.cs | 4 +- 15 files changed, 358 insertions(+), 265 deletions(-) delete mode 100644 Tzkt.Api/Utils/Converters/RawJsonConverter.cs create mode 100644 Tzkt.Api/Utils/JsonString.cs delete mode 100644 Tzkt.Api/Utils/StringAsJson.cs diff --git a/Tzkt.Api/Controllers/AccountsController.cs b/Tzkt.Api/Controllers/AccountsController.cs index 580056372..57dc28140 100644 --- a/Tzkt.Api/Controllers/AccountsController.cs +++ b/Tzkt.Api/Controllers/AccountsController.cs @@ -220,9 +220,9 @@ public async Task>> GetDelegators( /// Filters operations by level. /// Filters operations by timestamp. /// Filters transactions by entrypoint called on the target contract. - /// Filters transactions by parameters. Note, this query parameter supports the following format: `?params{.path?}{.mode?}=...`, - /// so you can specify a path to a particular field to filter by, for example: `?params.token_id=...` or `?params.sigs.0.ne=...`. - /// **DEPRECATED**. Use `entrypoint` and `params` instead. + /// Filters transactions by parameter value. Note, this query parameter supports the following format: `?parameter{.path?}{.mode?}=...`, + /// so you can specify a path to a particular field to filter by, for example: `?parameter.token_id=...` or `?parameter.sigs.0.ne=...`. + /// **DEPRECATED**. Use `entrypoint` and `parameter` instead. /// Filters transactions by presence of internal operations. /// Filters transactions, delegations, originations and reveals by operation status (`applied`, `failed`, `backtracked`, `skipped`). /// Sort mode (0 - ascending, 1 - descending) @@ -251,7 +251,7 @@ public async Task>> GetOperations( Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, StringParameter parameters, BoolParameter hasInternals, OperationStatusParameter status, @@ -382,7 +382,7 @@ public async Task>> GetOperations( if (to != null) timestamp.Lt = to.Value.DateTime; #endregion - return Ok(await Accounts.GetOperations(address, types, initiator, sender, target, prevDelegate, newDelegate, contractManager, contractDelegate, originatedContract, accuser, offender, baker, level, timestamp, entrypoint, @params, parameters, hasInternals, status, _sort, _offset, limit, micheline, quote)); + return Ok(await Accounts.GetOperations(address, types, initiator, sender, target, prevDelegate, newDelegate, contractManager, contractDelegate, originatedContract, accuser, offender, baker, level, timestamp, entrypoint, parameter, parameters, hasInternals, status, _sort, _offset, limit, micheline, quote)); } /// diff --git a/Tzkt.Api/Controllers/ContractsController.cs b/Tzkt.Api/Controllers/ContractsController.cs index 200eb5c19..005abce13 100644 --- a/Tzkt.Api/Controllers/ContractsController.cs +++ b/Tzkt.Api/Controllers/ContractsController.cs @@ -269,7 +269,7 @@ public async Task GetStorageSchema([Address] string address, [Min( /// Maximum number of items to return /// [HttpGet("{address}/storage/history")] - public Task> GetStorageHistory([Address] string address, [Min(0)] int lastId = 0, [Range(0, 1000)] int limit = 10) + public Task>> GetStorageHistory([Address] string address, [Min(0)] int lastId = 0, [Range(0, 1000)] int limit = 10) { return Accounts.GetStorageHistory(address, lastId, limit); } @@ -319,7 +319,7 @@ public Task GetRawStorageSchema([Address] string address, [Min(0)] i /// Maximum number of items to return /// [HttpGet("{address}/storage/raw/history")] - public Task> GetRawStorageHistory([Address] string address, [Min(0)] int lastId = 0, [Range(0, 1000)] int limit = 10) + public Task>> GetRawStorageHistory([Address] string address, [Min(0)] int lastId = 0, [Range(0, 1000)] int limit = 10) { return Accounts.GetRawStorageHistory(address, lastId, limit); } diff --git a/Tzkt.Api/Controllers/OperationsController.cs b/Tzkt.Api/Controllers/OperationsController.cs index 2c033eb6d..4e08034c3 100644 --- a/Tzkt.Api/Controllers/OperationsController.cs +++ b/Tzkt.Api/Controllers/OperationsController.cs @@ -1269,9 +1269,9 @@ public Task GetOriginationsCount( /// Filters transactions by timestamp. /// Filters transactions by presence of internal operations. /// Filters transactions by entrypoint called on the target contract. - /// Filters transactions by parameters. Note, this query parameter supports the following format: `?params{.path?}{.mode?}=...`, - /// so you can specify a path to a particular field to filter by, for example: `?params.token_id=...` or `?params.sigs.0.ne=...`. - /// **DEPRECATED**. Use `entrypoint` and `params` instead. + /// Filters transactions by parameter value. Note, this query parameter supports the following format: `?parameter{.path?}{.mode?}=...`, + /// so you can specify a path to a particular field to filter by, for example: `?parameter.token_id=...` or `?parameter.sigs.0.ne=...`. + /// **DEPRECATED**. Use `entrypoint` and `parameter` instead. /// Filters transactions by operation status (`applied`, `failed`, `backtracked`, `skipped`). /// Specify comma-separated list of fields to include into response or leave it undefined to return full object. If you select single field, response will be an array of values in both `.fields` and `.values` modes. /// Sorts transactions by specified field. Supported fields: `id` (default), `level`, `gasUsed`, `storageUsed`, `bakerFee`, `storageFee`, `allocationFee`, `amount`. @@ -1290,7 +1290,7 @@ public async Task>> GetTransactio Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, StringParameter parameters, BoolParameter hasInternals, OperationStatusParameter status, @@ -1352,25 +1352,25 @@ public async Task>> GetTransactio #endregion if (select == null) - return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, @params, parameters, hasInternals, status, sort, offset, limit, micheline, quote)); + return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, parameter, parameters, hasInternals, status, sort, offset, limit, micheline, quote)); if (select.Values != null) { if (select.Values.Length == 1) - return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, @params, hasInternals, status, sort, offset, limit, select.Values[0], micheline, quote)); + return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, parameter, hasInternals, status, sort, offset, limit, select.Values[0], micheline, quote)); else - return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, @params, hasInternals, status, sort, offset, limit, select.Values, micheline, quote)); + return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, parameter, hasInternals, status, sort, offset, limit, select.Values, micheline, quote)); } else { if (select.Fields.Length == 1) - return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, @params, hasInternals, status, sort, offset, limit, select.Fields[0], micheline, quote)); + return Ok(await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, parameter, hasInternals, status, sort, offset, limit, select.Fields[0], micheline, quote)); else { return Ok(new SelectionResponse { Cols = select.Fields, - Rows = await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, @params, hasInternals, status, sort, offset, limit, select.Fields, micheline, quote) + Rows = await Operations.GetTransactions(anyof, initiator, sender, target, amount, level, timestamp, entrypoint, parameter, hasInternals, status, sort, offset, limit, select.Fields, micheline, quote) }); } } diff --git a/Tzkt.Api/Models/Entrypoint.cs b/Tzkt.Api/Models/Entrypoint.cs index 39c510dfe..9b2c6b63a 100644 --- a/Tzkt.Api/Models/Entrypoint.cs +++ b/Tzkt.Api/Models/Entrypoint.cs @@ -14,9 +14,8 @@ public class Entrypoint /// /// A kind of JSON schema, describing how parameters will look like in a human-readable JSON format /// - [JsonConverter(typeof(RawJsonConverter))] [JsonSchemaType(typeof(object))] - public string JsonParameters { get; set; } + public JsonString JsonParameters { get; set; } /// /// Parameters schema in micheline format diff --git a/Tzkt.Api/Models/Operations/TransactionOperation.cs b/Tzkt.Api/Models/Operations/TransactionOperation.cs index ebd57e905..3e69d5c31 100644 --- a/Tzkt.Api/Models/Operations/TransactionOperation.cs +++ b/Tzkt.Api/Models/Operations/TransactionOperation.cs @@ -101,14 +101,9 @@ public class TransactionOperation : Operation public long Amount { get; set; } /// - /// Entrypoint called on the target contract - /// - public string Entrypoint { get; set; } - - /// - /// Parameters passed to the called entrypoint converted to human-readable JSON. Note: you can configure parameters format by setting `micheline` query parameter. + /// Transaction parameter, including called entrypoint and value passed to the entrypoint. /// - public object Params { get; set; } + public TxParameter Parameter { get; set; } /// /// Contract storage after executing the transaction converted to human-readable JSON. Note: you can configure storage format by setting `micheline` query parameter. @@ -143,8 +138,21 @@ public class TransactionOperation : Operation #endregion /// - /// **DEPRECATED**. Use `entrypoint` and `params` instead. + /// **DEPRECATED**. Use `entrypoint` and `parameter` instead. /// public string Parameters { get; set; } } + + public class TxParameter + { + /// + /// Entrypoint called on the target contract + /// + public string Entrypoint { get; set; } + + /// + /// Value passed to the called entrypoint converted to human-readable JSON. Note: you can configure parameters format by setting `micheline` query parameter. + /// + public object Value { get; set; } + } } diff --git a/Tzkt.Api/Models/StorageRecord.cs b/Tzkt.Api/Models/StorageRecord.cs index 194cae2b1..75307e1e3 100644 --- a/Tzkt.Api/Models/StorageRecord.cs +++ b/Tzkt.Api/Models/StorageRecord.cs @@ -1,11 +1,9 @@ using System; -using System.Text.Json.Serialization; using NJsonSchema.Annotations; -using Netezos.Encoding; namespace Tzkt.Api.Models { - public class StorageRecord + public class StorageRecord { /// /// Id of the record that can be used for pagination @@ -25,17 +23,16 @@ public class StorageRecord /// /// Operation that caused the storage change /// - public SourceOperation Operation { get; set; } + public SourceOperation Operation { get; set; } /// - /// New value of the storage + /// New storage value /// - [JsonConverter(typeof(RawJsonConverter))] [JsonSchemaType(typeof(object))] - public string Value { get; set; } + public T Value { get; set; } } - public class SourceOperation + public class SourceOperation { /// /// Operation type @@ -58,76 +55,22 @@ public class SourceOperation public int? Nonce { get; set; } /// - /// Called contract entrypoint + /// Transaction parameter, including called entrypoint and value passed to the entrypoint. /// - public string Entrypoint { get; set; } - - /// - /// Parameters passed - /// - [JsonConverter(typeof(RawJsonConverter))] - [JsonSchemaType(typeof(object))] - public string Params { get; set; } - } - - public class RawStorageRecord - { - /// - /// Id of the record that can be used for pagination - /// - public int Id { get; set; } - - /// - /// Level at which the storage value was taken - /// - public int Level { get; set; } - - /// - /// Timestamp at which the storage value was taken - /// - public DateTime Timestamp { get; set; } - - /// - /// Operation that caused the storage change - /// - public SourceOperationRaw Operation { get; set; } - - /// - /// New value of the storage - /// - public IMicheline Value { get; set; } + public SourceOperationParameter Parameter { get; set; } } - public class SourceOperationRaw + public class SourceOperationParameter { /// - /// Operation type - /// - public string Type { get; set; } - - /// - /// Operation hash - /// - public string Hash { get; set; } - - /// - /// Operation counter (null in case of synthetic operations) - /// - public int? Counter { get; set; } - - /// - /// Operation nonce (null in case of non-internal or synthetic operations) - /// - public int? Nonce { get; set; } - - /// - /// Called contract entrypoint + /// Called entrypoint /// public string Entrypoint { get; set; } /// - /// Parameters passed + /// Value passed to the entrypoint /// - public IMicheline Params { get; set; } + [JsonSchemaType(typeof(object))] + public T Value { get; set; } } } diff --git a/Tzkt.Api/Parameters/Binders/JsonBinder.cs b/Tzkt.Api/Parameters/Binders/JsonBinder.cs index 451267434..91cf68968 100644 --- a/Tzkt.Api/Parameters/Binders/JsonBinder.cs +++ b/Tzkt.Api/Parameters/Binders/JsonBinder.cs @@ -53,6 +53,50 @@ public Task BindModelAsync(ModelBindingContext bindingContext) res.Ne.Add((string.Join(',', arr[1..^1]), ne)); } break; + case "gt": + hasValue = false; + if (!bindingContext.TryGetString(key, ref hasValue, out var gt)) + return Task.CompletedTask; + if (hasValue) + { + res ??= new JsonParameter(); + res.Gt ??= new List<(string, string)>(); + res.Gt.Add((string.Join(',', arr[1..^1]), gt)); + } + break; + case "ge": + hasValue = false; + if (!bindingContext.TryGetString(key, ref hasValue, out var ge)) + return Task.CompletedTask; + if (hasValue) + { + res ??= new JsonParameter(); + res.Ge ??= new List<(string, string)>(); + res.Ge.Add((string.Join(',', arr[1..^1]), ge)); + } + break; + case "lt": + hasValue = false; + if (!bindingContext.TryGetString(key, ref hasValue, out var lt)) + return Task.CompletedTask; + if (hasValue) + { + res ??= new JsonParameter(); + res.Lt ??= new List<(string, string)>(); + res.Lt.Add((string.Join(',', arr[1..^1]), lt)); + } + break; + case "le": + hasValue = false; + if (!bindingContext.TryGetString(key, ref hasValue, out var le)) + return Task.CompletedTask; + if (hasValue) + { + res ??= new JsonParameter(); + res.Le ??= new List<(string, string)>(); + res.Le.Add((string.Join(',', arr[1..^1]), le)); + } + break; case "as": hasValue = false; if (!bindingContext.TryGetString(key, ref hasValue, out var @as)) diff --git a/Tzkt.Api/Parameters/JsonParameter.cs b/Tzkt.Api/Parameters/JsonParameter.cs index b12c5b42e..7a4f9f08c 100644 --- a/Tzkt.Api/Parameters/JsonParameter.cs +++ b/Tzkt.Api/Parameters/JsonParameter.cs @@ -11,7 +11,7 @@ public class JsonParameter /// **Equal** filter mode (optional, i.e. `param.eq=123` is the same as `param=123`). \ /// Specify a string to get items where the specified field is equal to the specified value. /// - /// Example: `?params={}` or `?params.to=tz1...`. + /// Example: `?parameter={}` or `?parameter.to=tz1...`. /// [JsonSchemaType(typeof(string))] public List<(string, string)> Eq { get; set; } @@ -20,17 +20,61 @@ public class JsonParameter /// **Not equal** filter mode. \ /// Specify a string to get items where the specified field is not equal to the specified value. /// - /// Example: `?params.ne={}` or `?params.amount.ne=0`. + /// Example: `?parameter.ne={}` or `?parameter.amount.ne=0`. /// [JsonSchemaType(typeof(string))] public List<(string, string)> Ne { get; set; } + /// + /// **Greater than** filter mode. \ + /// Specify a string to get items where the specified field is greater than the specified value. + /// Note that all stored JSON values are strings, so this will be a comparison of two strings, so we recommend comparing values of the same type, + /// e.g. numeric strings with numeric strings (`parameter.number.gt=123`), datetime strings with datetime strings (`parameter.date.gt=2021-01-01`), etc. + /// Otherwise, result may surprise you. + /// + /// Example: `?parameter.balance.gt=1234` or `?parameter.time.gt=2021-02-01`. + /// + public List<(string, string)> Gt { get; set; } + + /// + /// **Greater or equal** filter mode. \ + /// Specify a string to get items where the specified field is greater than equal to the specified value. + /// Note that all stored JSON values are strings, so this will be a comparison of two strings, so we recommend comparing values of the same type, + /// e.g. numeric strings with numeric strings (`parameter.number.gt=123`), datetime strings with datetime strings (`parameter.date.gt=2021-01-01`), etc. + /// Otherwise, result may surprise you. + /// + /// Example: `?parameter.balance.ge=1234` or `?parameter.time.ge=2021-02-01`. + /// + public List<(string, string)> Ge { get; set; } + + /// + /// **Less than** filter mode. \ + /// Specify a string to get items where the specified field is less than the specified value. + /// Note that all stored JSON values are strings, so this will be a comparison of two strings, so we recommend comparing values of the same type, + /// e.g. numeric strings with numeric strings (`parameter.number.gt=123`), datetime strings with datetime strings (`parameter.date.gt=2021-01-01`), etc. + /// Otherwise, result may surprise you. + /// + /// Example: `?parameter.balance.lt=1234` or `?parameter.time.lt=2021-02-01`. + /// + public List<(string, string)> Lt { get; set; } + + /// + /// **Less or equal** filter mode. \ + /// Specify a string to get items where the specified field is less than or equal to the specified value. + /// Note that all stored JSON values are strings, so this will be a comparison of two strings, so we recommend comparing values of the same type, + /// e.g. numeric strings with numeric strings (`parameter.number.gt=123`), datetime strings with datetime strings (`parameter.date.gt=2021-01-01`), etc. + /// Otherwise, result may surprise you. + /// + /// Example: `?parameter.balance.le=1234` or `?parameter.time.le=2021-02-01`. + /// + public List<(string, string)> Le { get; set; } + /// /// **Same as** filter mode. \ /// Specify a string template to get items where the specified field matches the specified template. \ /// This mode supports wildcard `*`. Use `\*` as an escape symbol. /// - /// Example: `?params.as=*mid*` or `?params.as=*end`. + /// Example: `?parameter.as=*mid*` or `?parameter.as=*end`. /// [JsonSchemaType(typeof(string))] public List<(string, string)> As { get; set; } @@ -40,7 +84,7 @@ public class JsonParameter /// Specify a string template to get items where the specified field doesn't match the specified template. /// This mode supports wildcard `*`. Use `\*` as an escape symbol. /// - /// Example: `?params.un=*mid*` or `?params.un=*end`. + /// Example: `?parameter.un=*mid*` or `?parameter.un=*end`. /// [JsonSchemaType(typeof(string))] public List<(string, string)> Un { get; set; } @@ -50,7 +94,7 @@ public class JsonParameter /// Specify a comma-separated list of strings to get items where the specified field is equal to one of the specified values. \ /// Use `\,` as an escape symbol. /// - /// Example: `?params.in=bla,bal,abl` or `?params.from.in=tz1,tz2,tz3`. + /// Example: `?parameter.in=bla,bal,abl` or `?parameter.from.in=tz1,tz2,tz3`. /// [JsonSchemaType(typeof(List))] public List<(string, List)> In { get; set; } @@ -60,7 +104,7 @@ public class JsonParameter /// Specify a comma-separated list of strings to get items where the specified field is not equal to all the specified values. \ /// Use `\,` as an escape symbol. /// - /// Example: `?params.ni=bla,bal,abl` or `?params.from.ni=tz1,tz2,tz3`. + /// Example: `?parameter.ni=bla,bal,abl` or `?parameter.from.ni=tz1,tz2,tz3`. /// [JsonSchemaType(typeof(List))] public List<(string, List)> Ni { get; set; } @@ -69,7 +113,7 @@ public class JsonParameter /// **Is null** filter mode. \ /// Use this mode to get items where the specified field is null or not. /// - /// Example: `?params.null` or `?params.null=false` or `?params.sigs.0.null=false`. + /// Example: `?parameter.null` or `?parameter.null=false` or `?parameter.sigs.0.null=false`. /// [JsonSchemaType(typeof(bool))] public List<(string, bool)> Null { get; set; } diff --git a/Tzkt.Api/Repositories/AccountRepository.cs b/Tzkt.Api/Repositories/AccountRepository.cs index e3a171860..885942fe3 100644 --- a/Tzkt.Api/Repositories/AccountRepository.cs +++ b/Tzkt.Api/Repositories/AccountRepository.cs @@ -2485,10 +2485,10 @@ ORDER BY ""ScriptLevel"" DESC return (Micheline.FromBytes(row.StorageSchema) as MichelinePrim).Args[0]; } - public async Task> GetStorageHistory(string address, int lastId, int limit) + public async Task>> GetStorageHistory(string address, int lastId, int limit) { var rawAccount = await Accounts.GetAsync(address); - if (rawAccount is not RawContract contract) return Enumerable.Empty(); + if (rawAccount is not RawContract contract) return Enumerable.Empty>(); using var db = GetConnection(); var rows = await db.QueryAsync($@" @@ -2519,33 +2519,36 @@ LEFT JOIN ""OriginationOps"" as o_op {(lastId > 0 ? $@"AND COALESCE(ss.""TransactionId"", ss.""OriginationId"", ss.""MigrationId"") < {lastId}" : "")} ORDER BY ss.""Level"" DESC, ss.""TransactionId"" DESC LIMIT {limit}"); - if (!rows.Any()) return Enumerable.Empty(); + if (!rows.Any()) return Enumerable.Empty>(); return rows.Select(row => { int id; DateTime timestamp; - SourceOperation source; + SourceOperation source; if (row.TransactionId != null) { id = row.TransactionId; timestamp = row.TransactionTimestamp; - source = new SourceOperation + source = new SourceOperation { Type = "transaction", Hash = row.TransactionHash, Counter = row.TransactionCounter, Nonce = row.TransactionNonce, - Entrypoint = row.TransactionEntrypoint, - Params = row.TransactionJsonParameters + Parameter = row.TransactionEntrypoint == null ? null : new SourceOperationParameter + { + Entrypoint = row.TransactionEntrypoint, + Value = row.TransactionJsonParameters + } }; } else if (row.OriginationId != null) { id = row.OriginationId; timestamp = row.OriginationTimestamp; - source = new SourceOperation + source = new SourceOperation { Type = "origination", Hash = row.OriginationHash, @@ -2557,13 +2560,13 @@ LEFT JOIN ""OriginationOps"" as o_op { id = row.MigrationId; timestamp = row.MigrationTimestamp; - source = new SourceOperation + source = new SourceOperation { Type = "migration" }; } - return new StorageRecord + return new StorageRecord { Id = id, Timestamp = timestamp, @@ -2574,10 +2577,10 @@ LEFT JOIN ""OriginationOps"" as o_op }); } - public async Task> GetRawStorageHistory(string address, int lastId, int limit) + public async Task>> GetRawStorageHistory(string address, int lastId, int limit) { var rawAccount = await Accounts.GetAsync(address); - if (rawAccount is not RawContract contract) return Enumerable.Empty(); + if (rawAccount is not RawContract contract) return Enumerable.Empty>(); using var db = GetConnection(); var rows = await db.QueryAsync($@" @@ -2608,35 +2611,38 @@ LEFT JOIN ""OriginationOps"" as o_op {(lastId > 0 ? $@"AND COALESCE(ss.""TransactionId"", ss.""OriginationId"", ss.""MigrationId"") < {lastId}" : "")} ORDER BY ss.""Level"" DESC, ss.""TransactionId"" DESC LIMIT {limit}"); - if (!rows.Any()) return Enumerable.Empty(); + if (!rows.Any()) return Enumerable.Empty>(); return rows.Select(row => { int id; DateTime timestamp; - SourceOperationRaw source; + SourceOperation source; if (row.TransactionId != null) { id = row.TransactionId; timestamp = row.TransactionTimestamp; - source = new SourceOperationRaw + source = new SourceOperation { Type = "transaction", Hash = row.TransactionHash, Counter = row.TransactionCounter, Nonce = row.TransactionNonce, - Entrypoint = row.TransactionEntrypoint, - Params = row.TransactionRawParameters != null - ? Micheline.FromBytes(row.TransactionRawParameters) - : null + Parameter = row.TransactionEntrypoint == null ? null : new SourceOperationParameter + { + Entrypoint = row.TransactionEntrypoint, + Value = row.TransactionRawParameters != null + ? Micheline.FromBytes(row.TransactionRawParameters) + : null + } }; } else if (row.OriginationId != null) { id = row.OriginationId; timestamp = row.OriginationTimestamp; - source = new SourceOperationRaw + source = new SourceOperation { Type = "origination", Hash = row.OriginationHash, @@ -2648,13 +2654,13 @@ LEFT JOIN ""OriginationOps"" as o_op { id = row.MigrationId; timestamp = row.MigrationTimestamp; - source = new SourceOperationRaw + source = new SourceOperation { Type = "migration" }; } - return new RawStorageRecord + return new StorageRecord { Id = id, Timestamp = timestamp, @@ -2804,7 +2810,7 @@ public async Task> GetOperations( Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, StringParameter parameters, BoolParameter hasInternals, OperationStatusParameter status, @@ -2860,7 +2866,7 @@ public async Task> GetOperations( : Task.FromResult(Enumerable.Empty()); var transactions = delegat.TransactionsCount > 0 && types.Contains(OpTypes.Transaction) - ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = delegat.Id }, initiator, sender, target, null, level, timestamp, entrypoint, @params, parameters, hasInternals, status, sort, offset, limit, format, quote) + ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = delegat.Id }, initiator, sender, target, null, level, timestamp, entrypoint, parameter, parameters, hasInternals, status, sort, offset, limit, format, quote) : Task.FromResult(Enumerable.Empty()); var reveals = delegat.RevealsCount > 0 && types.Contains(OpTypes.Reveal) @@ -2927,7 +2933,7 @@ await Task.WhenAll( : Task.FromResult(Enumerable.Empty()); var userTransactions = user.TransactionsCount > 0 && types.Contains(OpTypes.Transaction) - ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = user.Id }, initiator, sender, target, null, level, timestamp, entrypoint, @params, parameters, hasInternals, status, sort, offset, limit, format, quote) + ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = user.Id }, initiator, sender, target, null, level, timestamp, entrypoint, parameter, parameters, hasInternals, status, sort, offset, limit, format, quote) : Task.FromResult(Enumerable.Empty()); var userReveals = user.RevealsCount > 0 && types.Contains(OpTypes.Reveal) @@ -2966,7 +2972,7 @@ await Task.WhenAll( : Task.FromResult(Enumerable.Empty()); var contractTransactions = contract.TransactionsCount > 0 && types.Contains(OpTypes.Transaction) - ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = contract.Id }, initiator, sender, target, null, level, timestamp, entrypoint, @params, parameters, hasInternals, status, sort, offset, limit, format, quote) + ? Operations.GetTransactions(new AnyOfParameter { Fields = new[] { "initiator", "sender", "target" }, Value = contract.Id }, initiator, sender, target, null, level, timestamp, entrypoint, parameter, parameters, hasInternals, status, sort, offset, limit, format, quote) : Task.FromResult(Enumerable.Empty()); var contractReveals = contract.RevealsCount > 0 && types.Contains(OpTypes.Reveal) diff --git a/Tzkt.Api/Repositories/OperationRepository.cs b/Tzkt.Api/Repositories/OperationRepository.cs index 43719ab8b..747776dfb 100644 --- a/Tzkt.Api/Repositories/OperationRepository.cs +++ b/Tzkt.Api/Repositories/OperationRepository.cs @@ -3242,9 +3242,9 @@ LEFT JOIN ""Scripts"" as sc Code = (int)format % 2 == 0 ? code : code.ToJson(), Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -3321,9 +3321,9 @@ LEFT JOIN ""Scripts"" as sc Code = (int)format % 2 == 0 ? code : code.ToJson(), Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -3400,9 +3400,9 @@ LEFT JOIN ""Scripts"" as sc Code = (int)format % 2 == 0 ? code : code.ToJson(), Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -3759,9 +3759,9 @@ public async Task GetOriginations( foreach (var row in rows) result[j++][i] = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }; @@ -3991,9 +3991,9 @@ public async Task GetOriginations( foreach (var row in rows) result[j++] = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }; @@ -4084,20 +4084,23 @@ LEFT JOIN ""Storages"" as s AllocationFee = row.AllocationFee ?? 0, Target = row.TargetId != null ? Accounts.GetAlias(row.TargetId) : null, Amount = row.Amount, - Entrypoint = row.Entrypoint, - Params = format switch + Parameter = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }, Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -4144,20 +4147,23 @@ LEFT JOIN ""Storages"" as s AllocationFee = row.AllocationFee ?? 0, Target = row.TargetId != null ? Accounts.GetAlias(row.TargetId) : null, Amount = row.Amount, - Entrypoint = row.Entrypoint, - Params = format switch + Parameter = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }, Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -4204,20 +4210,23 @@ LEFT JOIN ""Storages"" as s AllocationFee = row.AllocationFee ?? 0, Target = row.TargetId != null ? Accounts.GetAlias(row.TargetId) : null, Amount = row.Amount, - Entrypoint = row.Entrypoint, - Params = format switch + Parameter = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }, Storage = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }, @@ -4260,14 +4269,17 @@ public async Task> GetTransactions(Block block AllocationFee = row.AllocationFee ?? 0, Target = row.TargetId != null ? Accounts.GetAlias(row.TargetId) : null, Amount = row.Amount, - Entrypoint = row.Entrypoint, - Params = format switch + Parameter = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }, Status = StatusToString(row.Status), Errors = row.Errors != null ? OperationErrorSerializer.Deserialize(row.Errors) : null, @@ -4286,7 +4298,7 @@ public async Task> GetTransactions( Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, StringParameter parameters, BoolParameter hasInternals, OperationStatusParameter status, @@ -4316,7 +4328,7 @@ public async Task> GetTransactions( .Filter("TargetId", target, x => x == "sender" ? "SenderId" : "InitiatorId") .Filter("Amount", amount) .Filter("Entrypoint", entrypoint) - .Filter("JsonParameters", @params) + .Filter("JsonParameters", parameter) .Filter("InternalOperations", hasInternals?.Eq == true ? new Int32NullParameter { Gt = 0 } : hasInternals?.Eq == false @@ -4360,14 +4372,17 @@ public async Task> GetTransactions( AllocationFee = row.AllocationFee ?? 0, Target = row.TargetId != null ? Accounts.GetAlias(row.TargetId) : null, Amount = row.Amount, - Entrypoint = row.Entrypoint, - Params = format switch + Parameter = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }, Status = StatusToString(row.Status), Errors = row.Errors != null ? OperationErrorSerializer.Deserialize(row.Errors) : null, @@ -4453,7 +4468,7 @@ public async Task GetTransactions( Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, BoolParameter hasInternals, OperationStatusParameter status, SortParameter sort, @@ -4487,8 +4502,8 @@ public async Task GetTransactions( case "allocationFee": columns.Add(@"o.""AllocationFee"""); break; case "target": columns.Add(@"o.""TargetId"""); break; case "amount": columns.Add(@"o.""Amount"""); break; - case "entrypoint": columns.Add(@"o.""Entrypoint"""); break; - case "params": + case "parameter": + columns.Add(@"o.""Entrypoint"""); columns.Add(format switch { MichelineFormat.Json => $@"o.""JsonParameters""", @@ -4534,7 +4549,7 @@ public async Task GetTransactions( .Filter("TargetId", target, x => x == "sender" ? "SenderId" : "InitiatorId") .Filter("Amount", amount) .Filter("Entrypoint", entrypoint) - .Filter("JsonParameters", @params) + .Filter("JsonParameters", parameter) .Filter("InternalOperations", hasInternals?.Eq == true ? new Int32NullParameter { Gt = 0 } : hasInternals?.Eq == false @@ -4638,28 +4653,28 @@ public async Task GetTransactions( foreach (var row in rows) result[j++][i] = row.Amount; break; - case "entrypoint": - foreach (var row in rows) - result[j++][i] = row.Entrypoint; - break; - case "params": + case "parameter": foreach (var row in rows) - result[j++][i] = format switch + result[j++][i] = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }; break; case "storage": foreach (var row in rows) result[j++][i] = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }; @@ -4700,7 +4715,7 @@ public async Task GetTransactions( Int32Parameter level, DateTimeParameter timestamp, StringParameter entrypoint, - JsonParameter @params, + JsonParameter parameter, BoolParameter hasInternals, OperationStatusParameter status, SortParameter sort, @@ -4732,8 +4747,8 @@ public async Task GetTransactions( case "allocationFee": columns.Add(@"o.""AllocationFee"""); break; case "target": columns.Add(@"o.""TargetId"""); break; case "amount": columns.Add(@"o.""Amount"""); break; - case "entrypoint": columns.Add(@"o.""Entrypoint"""); break; - case "params": + case "parameter": + columns.Add(@"o.""Entrypoint"""); columns.Add(format switch { MichelineFormat.Json => $@"o.""JsonParameters""", @@ -4778,7 +4793,7 @@ public async Task GetTransactions( .Filter("TargetId", target, x => x == "sender" ? "SenderId" : "InitiatorId") .Filter("Amount", amount) .Filter("Entrypoint", entrypoint) - .Filter("JsonParameters", @params) + .Filter("JsonParameters", parameter) .Filter("InternalOperations", hasInternals?.Eq == true ? new Int32NullParameter { Gt = 0 } : hasInternals?.Eq == false @@ -4880,28 +4895,28 @@ public async Task GetTransactions( foreach (var row in rows) result[j++] = row.Amount; break; - case "entrypoint": + case "parameter": foreach (var row in rows) - result[j++] = row.Entrypoint; - break; - case "params": - foreach (var row in rows) - result[j++] = format switch + result[j++] = row.Entrypoint == null ? null : new TxParameter { - MichelineFormat.Json => row.JsonParameters == null ? null : new StringAsJson(row.JsonParameters), - MichelineFormat.JsonString => row.JsonParameters, - MichelineFormat.Raw => row.RawParameters == null ? null : new StringAsJson(Micheline.ToJson(row.RawParameters)), - MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), - _ => throw new Exception("Invalid MichelineFormat value") + Entrypoint = row.Entrypoint, + Value = format switch + { + MichelineFormat.Json => row.JsonParameters == null ? null : new JsonString(row.JsonParameters), + MichelineFormat.JsonString => row.JsonParameters, + MichelineFormat.Raw => row.RawParameters == null ? null : new JsonString(Micheline.ToJson(row.RawParameters)), + MichelineFormat.RawString => row.RawParameters == null ? null : Micheline.ToJson(row.RawParameters), + _ => throw new Exception("Invalid MichelineFormat value") + } }; break; case "storage": foreach (var row in rows) result[j++] = format switch { - MichelineFormat.Json => row.JsonValue == null ? null : new StringAsJson(row.JsonValue), + MichelineFormat.Json => row.JsonValue == null ? null : new JsonString(row.JsonValue), MichelineFormat.JsonString => row.JsonValue, - MichelineFormat.Raw => row.RawValue == null ? null : new StringAsJson(Micheline.ToJson(row.RawValue)), + MichelineFormat.Raw => row.RawValue == null ? null : new JsonString(Micheline.ToJson(row.RawValue)), MichelineFormat.RawString => row.RawValue == null ? null : Micheline.ToJson(row.RawValue), _ => throw new Exception("Invalid MichelineFormat value") }; diff --git a/Tzkt.Api/Utils/Converters/RawJsonConverter.cs b/Tzkt.Api/Utils/Converters/RawJsonConverter.cs deleted file mode 100644 index b4e0fb8eb..000000000 --- a/Tzkt.Api/Utils/Converters/RawJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Tzkt.Api -{ - class RawJsonConverter : JsonConverter - { - public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) - { - using var json = JsonDocument.Parse(value); - json.WriteTo(writer); - } - } -} diff --git a/Tzkt.Api/Utils/JsonString.cs b/Tzkt.Api/Utils/JsonString.cs new file mode 100644 index 000000000..ee7dfcac1 --- /dev/null +++ b/Tzkt.Api/Utils/JsonString.cs @@ -0,0 +1,30 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Tzkt.Api +{ + [JsonConverter(typeof(JsonStringConverter))] + public class JsonString + { + public string Json { get; } + public JsonString(string json) => Json = json; + + public static implicit operator JsonString (string value) => new JsonString(value); + public static explicit operator string (JsonString value) => value.Json; + } + + class JsonStringConverter : JsonConverter + { + public override JsonString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, JsonString value, JsonSerializerOptions options) + { + using var doc = JsonDocument.Parse(value.Json, new JsonDocumentOptions { MaxDepth = 1024 }); + doc.WriteTo(writer); + } + } +} diff --git a/Tzkt.Api/Utils/SqlBuilder.cs b/Tzkt.Api/Utils/SqlBuilder.cs index ca77a44a3..5753d2209 100644 --- a/Tzkt.Api/Utils/SqlBuilder.cs +++ b/Tzkt.Api/Utils/SqlBuilder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Dapper; @@ -382,6 +383,58 @@ public SqlBuilder Filter(string column, JsonParameter json, Func } } + if (json.Gt != null) + { + foreach (var (path, value) in json.Gt) + { + var col = $@"""{column}""#>>'{{{path}}}'"; + var len = $"greatest(length({col}), {value.Length})"; + AppendFilter(Regex.IsMatch(value, "^[0-9]+$") + ? $@"lpad({col}, {len}, '0') > lpad(@p{Counter}, {len}, '0')" + : $@"{col} > @p{Counter}"); + Params.Add($"p{Counter++}", value); + } + } + + if (json.Ge != null) + { + foreach (var (path, value) in json.Ge) + { + var col = $@"""{column}""#>>'{{{path}}}'"; + var len = $"greatest(length({col}), {value.Length})"; + AppendFilter(Regex.IsMatch(value, "^[0-9]+$") + ? $@"lpad({col}, {len}, '0') >= lpad(@p{Counter}, {len}, '0')" + : $@"{col} >= @p{Counter}"); + Params.Add($"p{Counter++}", value); + } + } + + if (json.Lt != null) + { + foreach (var (path, value) in json.Lt) + { + var col = $@"""{column}""#>>'{{{path}}}'"; + var len = $"greatest(length({col}), {value.Length})"; + AppendFilter(Regex.IsMatch(value, "^[0-9]+$") + ? $@"lpad({col}, {len}, '0') < lpad(@p{Counter}, {len}, '0')" + : $@"{col} < @p{Counter}"); + Params.Add($"p{Counter++}", value); + } + } + + if (json.Le != null) + { + foreach (var (path, value) in json.Le) + { + var col = $@"""{column}""#>>'{{{path}}}'"; + var len = $"greatest(length({col}), {value.Length})"; + AppendFilter(Regex.IsMatch(value, "^[0-9]+$") + ? $@"lpad({col}, {len}, '0') <= lpad(@p{Counter}, {len}, '0')" + : $@"{col} <= @p{Counter}"); + Params.Add($"p{Counter++}", value); + } + } + if (json.As != null) { foreach (var (path, value) in json.As) diff --git a/Tzkt.Api/Utils/StringAsJson.cs b/Tzkt.Api/Utils/StringAsJson.cs deleted file mode 100644 index 9a341bbd7..000000000 --- a/Tzkt.Api/Utils/StringAsJson.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Tzkt.Api -{ - [JsonConverter(typeof(StringAsJsonConverter))] - public class StringAsJson - { - public string Json { get; } - public StringAsJson(string json) => Json = json; - } - - class StringAsJsonConverter : JsonConverter - { - public override StringAsJson Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, StringAsJson value, JsonSerializerOptions options) - { - using var doc = JsonDocument.Parse(value.Json, new JsonDocumentOptions { MaxDepth = 1024 }); - doc.WriteTo(writer); - } - } -} diff --git a/Tzkt.Sync/Protocols/Handlers/Proto5/Commits/Operations/TransactionsCommit.cs b/Tzkt.Sync/Protocols/Handlers/Proto5/Commits/Operations/TransactionsCommit.cs index 4b22043c5..169a89f9b 100644 --- a/Tzkt.Sync/Protocols/Handlers/Proto5/Commits/Operations/TransactionsCommit.cs +++ b/Tzkt.Sync/Protocols/Handlers/Proto5/Commits/Operations/TransactionsCommit.cs @@ -38,9 +38,7 @@ protected override async Task ProcessParameters(TransactionOperation transaction transaction.Entrypoint = normEp; transaction.RawParameters = normParam.ToBytes(); - - if (contract.Kind > ContractKind.DelegatorContract) - transaction.JsonParameters = schema.HumanizeParameter(normEp, normParam); + transaction.JsonParameters = schema.HumanizeParameter(normEp, normParam); } catch (Exception ex) {