-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a Mirror Node GraphQL API #668
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Steven Sheehy <steven.sheehy@swirldslabs.com>
✅ Deploy Preview for hedera-hips ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
The admin key associated with this entity whose signing requirements must be met in order to modify the entity on | ||
the network. | ||
""" | ||
key: Object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dynamic structure is a bit unique. Need to document it separately somewhere.
HIP/HIP-668.md
Outdated
"An ISO 8601 compatible duration with support for nanoseconds granularity in the format P[n]Y[n]M[n]DT[n]H[n]M[n]S." | ||
scalar Duration | ||
|
||
"A 64-bit numeric type." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed or unsigned? I think it should be explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, will add a note that it's signed. Built-in types like Int
are signed and this one will be as well, especially since it's backed by Java which only has signed.
type EntityId { | ||
"The unique incrementing identifier associated with this entity." | ||
num: Long! | ||
|
||
"The realm number. Currently always zero." | ||
realm: Long! | ||
|
||
"The shard number to allow for horizontal scaling of networks. Currently always zero." | ||
shard: Long! | ||
} | ||
|
||
"The unique identifier to find an entity on the Hedera network." | ||
input EntityIdInput { | ||
"The unique incrementing identifier associated with this entity." | ||
num: Long! @Min(value: 0) | ||
|
||
"The realm number. Defaults to zero." | ||
realm: Long! = 0 @Min(value: 0) | ||
|
||
"The shard number to allow for horizontal scaling of networks. Defaults to zero." | ||
shard: Long! = 0 @Min(value: 0) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do people prefer the EntityId as a complex type or due to its wide use in the API prefer it as a 0.0.x
scalar string like the REST API? It can get quite verbose to query for all these entity ids as accountId {shard, realm, num}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the scalar string since its all 0 shard 0 realm for now.
Just my two cents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go with the complex type. I appreciate the 0 defaults and the verbosity but I think that's something that can be managed at the client level
Signed-off-by: Steven Sheehy <steven.sheehy@swirldslabs.com>
Signed-off-by: Michael Garber <michael.garber@swirldslabs.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had thought I had submitted this last week, but I was just prompted to finish this review. Sorry for the delay.
Looks very good, just a few (3) nits.
GraphQL. Data should be nested and allow for pagination at different levels. Strongly typed objects should be preferred | ||
over complex string representations of multi-field objects similar to the protobuf-based HAPI. For example, the | ||
transaction ID `0.0.289304-1673028763-068736176` in the current API could be a GraphQL type `TransactionId` with | ||
`nonce`, `payerAccountId`, `scheduled`, and `validStart` fields where even those could be complex types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example isn't very clear. 0.0.289304
is probably the payerAccountId
; I'm guessing 1673028763
is the validStart
, so then 068736176
is either the nonce
or scheduled
-- but isn't one of those fields missing? Maybe make sure the fields appear in the same order in the TransactionId
as they do, spelled out, and the example would be much clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the example string and just use the generic term string so as to not cause confusion and focus on the details of the old approach. The idea was to show that request/response is more strongly typed objects now, not to show how things map from the old to the new.
HIP/HIP-668.md
Outdated
|
||
The new GraphQL API will be written as a new module in the open source Hedera Mirror Node repository. It will be Java | ||
based to allow for code reuse with its other modules. It will interact directly with the SQL database like the other | ||
modules. Creating it as separate module will allow it to be a microservice that can be scaled separately from other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(grammar) suggestion: add the word "a" between "as" and "separate module"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, added a
.
"A rational number, used to provide an accurate number without any rounding issues and to provide consistency with HAPI." | ||
type Fraction { | ||
"The rational's denominator. Will be a value of one when the numerator should be treated as a whole number." | ||
denominator: Long! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have a minimum value of 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not an input
, only a response type
.
Here are the various search forms enabled by HashScan:
If we want to implement HashScan search with GraphQL, we would need something like this:
|
Also I see |
Call below returns one or zero transaction:
Multiple transactions may have the same transaction id. Shouldn't we have an additional call like this ?
|
To implement EIP 3091, HashScan needs to retrieve a transaction matching an Ethereum hash. Shouldn't we add this capability in GraphQL interface ?
|
Signed-off-by: Steven Sheehy <steven.sheehy@swirldslabs.com>
Thanks, renamed. |
This is good feedback. Unfortunately, we do not want to expose transaction hash until we have a scalable solution and it's implemented in all environments and supports more than just recent data. Definitely something that we want to add in the future, though. For public key, the unfortunate problem is that users are free to create an unbounded number of accounts with the same public key. So if we want to support search by key then it would have to be a pageable |
I've added the ability to search for a contract result by its ethereum hash, but it still requires a contract ID first. I think once we have the search for transaction by hash we can just utilize that for EIP 3091. Until then, you can keep using the REST API approach. |
Signed-off-by: Steven Sheehy <steven.sheehy@swirldslabs.com>
Yes, I was holding off on it until the dust settled on HIP-631 since it was adding multiple such virtual addresses. Since that has been delayed until Q3 and they're using the alias terminology, I went ahead and added the |
Signed-off-by: Steven Sheehy <steven.sheehy@swirldslabs.com>
I was thinking just to return the successful one. Or to return one of the errored ones if only errors. But that's probably not ideal for all scenarios. So I changed it to return a list. Note I named it as |
Signed-off-by: Michael Garber <michael.garber@swirldslabs.com>
## Motivation | ||
|
||
The current mirror node REST API provides a functional API that returns most of the data users need. However, due to the | ||
nature of REST APIs, it suffers from problems inherit in REST itself including both under-fetching and over-fetching. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think you meant
nature of REST APIs, it suffers from problems inherit in REST itself including both under-fetching and over-fetching. | |
nature of REST APIs, it suffers from problems inherent to REST itself including both under-fetching and over-fetching. |
the transaction ID being a string as in the REST API, it could be a GraphQL type `TransactionId` with | ||
`nonce`, `payerAccountId`, `scheduled`, and `validStart` fields where even those could be complex types. | ||
|
||
An existing GraphQL API for the Hedera network was created by community members under the name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this better located in the rejected ideas section?
graphs of data. The open source mirror node does not provide any guarantees of database schema compatibility between | ||
releases so this schema will become harder to maintain over time without the use of a view model abstraction layer. | ||
|
||
[The Graph](https://thegraph.com/) provides an indexing protocol for networks and allows anyone to publish sub-graphs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure it's necessary to mention The Graph. As you noted it's main purpose is the indexing of data and GraphQL is used to expose the data. The mixup only occurs in the API choice and not the main problem being solved.
Maybe another section to move to rejected ideas.
type EntityId { | ||
"The unique incrementing identifier associated with this entity." | ||
num: Long! | ||
|
||
"The realm number. Currently always zero." | ||
realm: Long! | ||
|
||
"The shard number to allow for horizontal scaling of networks. Currently always zero." | ||
shard: Long! | ||
} | ||
|
||
"The unique identifier to find an entity on the Hedera network." | ||
input EntityIdInput { | ||
"The unique incrementing identifier associated with this entity." | ||
num: Long! @Min(value: 0) | ||
|
||
"The realm number. Defaults to zero." | ||
realm: Long! = 0 @Min(value: 0) | ||
|
||
"The shard number to allow for horizontal scaling of networks. Defaults to zero." | ||
shard: Long! = 0 @Min(value: 0) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go with the complex type. I appreciate the 0 defaults and the verbosity but I think that's something that can be managed at the client level
} | ||
|
||
"An identifier that represents a well-known or always changing block in the network." | ||
enum BlockType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block types also have the following labels
pending
- Not applicable to Hedera due to our consensus but it's often used by devs and maps to thelatest
safe
- ... more details in link belowfinalized
- ... more details in link below
More info here https://github.com/ethereum/execution-apis/blob/main/src/schemas/block.yaml#L100
I think Safe and Finalized may also be treated like
key: Object | ||
|
||
"The memo associated with the entity." | ||
memo: String! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With HIP 729 we should add nonce to this.
Description:
Related issue(s):
Notes for reviewer:
Checklist