Skip to content

Commit

Permalink
Add API endpoints for global constants
Browse files Browse the repository at this point in the history
  • Loading branch information
Groxan committed Nov 22, 2021
1 parent 424dab1 commit c1921a6
Show file tree
Hide file tree
Showing 6 changed files with 446 additions and 0 deletions.
120 changes: 120 additions & 0 deletions Tzkt.Api/Controllers/ConstantsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

using Tzkt.Api.Models;
using Tzkt.Api.Repositories;
using Tzkt.Api.Services.Cache;

namespace Tzkt.Api.Controllers
{
[ApiController]
[Route("v1/constants")]
public class ConstantsController : ControllerBase
{
private readonly ConstantsRepository Constants;
private readonly StateCache State;

public ConstantsController(ConstantsRepository constants, StateCache state)
{
Constants = constants;
State = state;
}

/// <summary>
/// Get global constants
/// </summary>
/// <remarks>
/// Returns a list of global constants.
/// </remarks>
/// <param name="address">Filters constants by global address (starts with `expr..`).</param>
/// <param name="creationLevel">Filters constants by creation level.</param>
/// <param name="creationTime">Filters constants by creation time.</param>
/// <param name="creator">Filters constants by creator.</param>
/// <param name="refs">Filters constants by number of refs.</param>
/// <param name="size">Filters constants by size in bytes.</param>
/// <param name="select">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.</param>
/// <param name="sort">Sorts delegators by specified field. Supported fields: `id` (default), `creationLevel`, `size`, `refs`.</param>
/// <param name="offset">Specifies which or how many items should be skipped</param>
/// <param name="limit">Maximum number of items to return</param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult<IEnumerable<Constant>>> Get(
ExpressionParameter address,
Int32Parameter creationLevel,
TimestampParameter creationTime,
AccountParameter creator,
Int32Parameter refs,
Int32Parameter size,
SelectParameter select,
SortParameter sort,
OffsetParameter offset,
[Range(0, 10000)] int limit = 100)
{
#region validate
if (sort != null && !sort.Validate("creationLevel", "size", "refs"))
return new BadRequest($"{nameof(sort)}", "Sorting by the specified field is not allowed.");
#endregion

if (select == null)
return Ok(await Constants.Get(address, creationLevel, creationTime, creator, refs, size, sort, offset, limit));

if (select.Values != null)
{
if (select.Values.Length == 1)
return Ok(await Constants.Get(address, creationLevel, creationTime, creator, refs, size, sort, offset, limit, select.Values[0]));
else
return Ok(await Constants.Get(address, creationLevel, creationTime, creator, refs, size, sort, offset, limit, select.Values));
}
else
{
if (select.Fields.Length == 1)
return Ok(await Constants.Get(address, creationLevel, creationTime, creator, refs, size, sort, offset, limit, select.Fields[0]));
else
{
return Ok(new SelectionResponse
{
Cols = select.Fields,
Rows = await Constants.Get(address, creationLevel, creationTime, creator, refs, size, sort, offset, limit, select.Fields)
});
}
}
}

/// <summary>
/// Get global constant by address
/// </summary>
/// <remarks>
/// Returns global constant with specified address (expression hash).
/// </remarks>
/// <param name="address">Global address (starts with `expr..`)</param>
/// <returns></returns>
[HttpGet("{address}")]
public async Task<Constant> GetByAddress(
[Required][ExpressionHash] string address)
{
var res = await Constants.Get(address, null, null, null, null, null, null, null, 1);
return res.FirstOrDefault();
}

/// <summary>
/// Get global constants count
/// </summary>
/// <remarks>
/// Returns a number of global constants.
/// </remarks>
/// <param name="refs">Filters constants by number of refs.</param>
/// <returns></returns>
[HttpGet("count")]
public Task<int> GetCount(Int32Parameter refs)
{
if (refs == null)
return Task.FromResult(State.Current.ConstantsCount);

return Constants.GetCount();
}
}
}
48 changes: 48 additions & 0 deletions Tzkt.Api/Models/Constant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Netezos.Encoding;
using System;

namespace Tzkt.Api.Models
{
public class Constant
{
/// <summary>
/// Global address (expression hash)
/// </summary>
public string Address { get; set; }

/// <summary>
/// Constant micheline expression
/// </summary>
public IMicheline Value { get; set; }

/// <summary>
/// Constant size in bytes
/// </summary>
public int Size { get; set; }

/// <summary>
/// Number of contracts referencing this constant
/// </summary>
public int Refs { get; set; }

/// <summary>
/// Account registered this constant
/// </summary>
public Alias Creator { get; set; }

/// <summary>
/// Level of the first block baked with this software
/// </summary>
public int CreationLevel { get; set; }

/// <summary>
/// Datetime of the first block baked with this software
/// </summary>
public DateTime CreationTime { get; set; }

/// <summary>
/// Offchain metadata
/// </summary>
public RawJson Metadata { get; set; }
}
}
4 changes: 4 additions & 0 deletions Tzkt.Api/Parameters/ExpressionParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ public class ExpressionParameter
/// Example: `?address.ni=expr1,expr2`.
/// </summary>
public List<string> Ni { get; set; }

#region operators
public static implicit operator ExpressionParameter(string value) => new() { Eq = value };
#endregion
}
}
Loading

0 comments on commit c1921a6

Please sign in to comment.