cardano-foundation / cardano-graphql Goto Github PK
View Code? Open in Web Editor NEWGraphQL API for Cardano
License: Apache License 2.0
GraphQL API for Cardano
License: Apache License 2.0
Currently the Transaction.block
field is nullable to handle both the initial state of a transaction prior to it being included in a block. It would be better to define a type that extends the base transaction with chain information
Poll the API for changes, publish as subscription
This is a UX tweak that makes sense to handle as a specific case. Consider the following query:
{
blocks(
# limit is defaulting to 1 here since not specified
where: {
number: {
_in: [1,2] # implied to be asking for more than the default
}
}
) {
number
}
}
result:
{
"data": {
"blocks": [
{
"number": 1
}
]
}
}
It's a reasonable expectation to omit the limit argument when asking for a specific set of items without exceeding the limit
The current implementation exposes basic aggregation queries for fields appropriate for the domain. There are more complex queries that can easily be exposed, however this requires an alternative data source to make assertions to prove validity
Currently the server allows all origins, which satisfies the dev requirement, but is unsuitable for production. cors
is a property of the ApolloServer
config object, and it should be exposed in full. https://github.com/expressjs/cors#cors
cardano: Cardano
... should be
cardano: Cardano!
The current test scope does not include the full request, as the HTTP server gets in the way of tooling such as WallabyJS, and the GraphQL executable schema can be tested directly. It would be best to add an e2e test with Cardano GraphQL started in a Docker container, to be hooked into the CI for full assurance in one of our supported targets.
_and_: [Some_bool_exp]
_not: Some_bool_exp
_or: [Some_bool_exp]
Hasura exposes the GraphQL HTTP endpoint before it has fully completed the metadata import. It's possible to call the API without the permissions being applied, resulting in return values of null
. This was detected on our CI server
This will be useful for integrating services
type Address {
balance: BigInt!
inputs: [TransactionInput]
outputs: [TransactionOutput]
transactions(
limit: PositiveInt
offset: PositiveInt
order_by: transactions_order_by
where: transactions_filter
): [Transaction]
}
type Query {
addresses(
limit: PositiveInt
offset: PositiveInt
order: address_order_by
where: address_filter
) [Address!]!
}
Commented fields should be considered for future designs, not included in the MVP
enum Currency {
ADA
}
type CurrencyValue {
currency: Currency!
value: Int!
}
type Epoch {
blocks: [Block]!
output: [CurrencyValue]!
number: Int
slots: [Slot!]!
startedAt: DateTime!
endedAt: DateTime
transactions: [Transaction]
transactionsCount: Int
}
input EpochFilter {
numbers: [Int],
# beforeDate: DateTime,
# afterDate: DateTime
}
type Query {
epoch(filter: EpochFilter) Epoch
}
Restricted to the Playground client
Mapped from block.slot_leader
in DB
We will know when the data source has changed, so can reliably cache results for subsequent requests
The meta
fields can be added to the Cardano
view instead of defining a separate view, which then simplifies the resolver to:
cardano: (_root, _args, context, info) => {
// Could optimise, but there's little performance gain
return delegateToSchema({
context,
fieldName: 'Cardano',
info,
operation: 'query',
schema: context.hasura
})
}
Currently we're over-fetching data from postgres when the GraphQL query only requires a subset. This is an improvement over a REST API since we've moved the burden to the server, however ideally the SQL queries should be build dynamically with an exact query
This is an optimisation that has no impact on the API consumers.
The database now offers a denormalised field that would be the most performant over the aggregated query we currently have. It's worth exposing it at the top level
Block {
...
transactionCount: BigInt!
transactions_aggregate: Transaction_aggregate!
}
Transaction search is currently limited to id and block.
The aggregate fields should also have the associated *_bool_exp
args, to allow for the same filtering as non-aggegated fields of the same type
Placeholder to update, as it will be a breaking change
input-output-hk/cardano-explorer#135
To remove the dependance on cardano-explorer, we want cardano-graphql to apply the views it depends on at boot.
retry-as-promised will be used to attempt the application of the views until it succeeds (as we have no control over when the underlying tables will be created by cardano-explorer)
There are 2 potential pitfalls with this approach:
create view if not exists
statements executeThe first implementation will use the block's timestamp once it's added to the schema. This can be upgraded when support for mempool interactions are added to the node client
The write service now stores the transaction size in the db, which is good information to have in our API
This query: https://github.com/input-output-hk/cardano-explorer-app/blob/develop/source/features/blocks/api/getBlocksInRange.graphql
... when selecting the epoch number: https://github.com/input-output-hk/cardano-explorer-app/blob/develop/source/features/blocks/api/BlockOverview.graphql#L4-L6
performs poorly.
Need to investigate the cause
The current interface has basic selection controls with no control over ordering, and does not include pagination parameters.
Current:
{
blocks(filter: { numbers: [1,3,4] } ) {
id
number
}
}
Desired
{
blocks(limit: 250, offset: 100, where: { number: { _gt: 30, _lt: 100 }}) {
id
number
}
}
Poll the API for changes, publish as subscription
We can use this information to flesh out the Cardano
type:
protocolConst
slotDuration
startTime
type Cardano {
blockHeight: Int!
currentEpoch: Epoch!
protocolConst: Int
slotDuration: Int!
slotsPerEpoch: Int!
startTime: DateTime
}
Also need to make the current slot in the current epoch known, to enable a UI to display a percentage indicator
Currently querying epochs using an order_by
argument performs poorly due since the nature of the database design is not optimised for read performance.
{
epochs(limit: 5, order_by: { number: desc }) {
...
}
}
Instead, the recommended approach is to get the current epoch:
{
cardano {
currentEpoch
}
}
then select the epochs by number (eg latest from the above query is 35):
{
epochs(where: { number: { in: [35,34,33,32,31]}}) {
...
}
}
The database will either provide a notification on each block written, or this can be determined by polling at double the block production rate. GraphQL context can be used to globally reject or decorate new queries if it appears the database is stale, and open subscriptions be handled appropriately.
IntersectMBO/cardano-db-sync#33
https://github.com/input-output-hk/cardano-db-sync/blob/master/doc/interesting-queries.md
Currently we're assigning a random port during dev, and throwing an error if not explicitly set.
We're currently defaulting Block.slotWithinEpoch
to 0
, which is invalid
null
slot number is appropriate for EBBs and genesis
When creating a release we should update our running task definition to use these most recent containers.
This will probably be achieved best with a deploy.js
that leverages the aws-sdk to describe the currently running task, and apply updates to the container version of task defs.
Due to performance issues with the calculated dates, we elected to remove this field in https://github.com/input-output-hk/cardano-graphql/pull/42/files
It's expected to be restored within 24hrs
Currently the limit
param on queries have default values, but this can lead to confusion as the limit is applied transparently. It would be better to remove defaults, and instead require explicit values based on use-case
This needs to correlate with a test suite running against different Node.js targets
Due to the underlying data structure slots without blocks will not appear in the current query result sets. Initially this was implemented but presented a significant performance tax when joining objects to a view already derived from a recursive CTE.
This is an important domain-specific query relating to Stake Pool performance, so while a natural query expression of:
{
Slot(where: {block: {id: {_is_null: true}}}) {
number
}
}
...will return no results, a specific query for stakePoolPerformance
can be implemented without compromising performance, and provide greater value to the consumer
Result sets can be ordered by the result of aggregations, which is not currently exposed
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.