Using GraphQL RPC
This guide provides practical examples for querying the Sui network using GraphQL. For core concepts like headers, variables, fragments, pagination, scope, and limits, see the corresponding concepts page.
Access the GraphQL service for Sui RPC through an online IDE that provides a complete toolbox for fetching data and executing transactions on the network:
- Mainnet: https://graphql.mainnet.sui.io/graphql
- Testnet: https://graphql.testnet.sui.io/graphql
- Devnet: https://graphql.devnet.sui.io/graphql
Both Mainnet and Testnet services are rate-limited to keep network throughput optimized. These services are provided as a public good from Sui Foundation and are not meant for production-grade use. Refer to the list of RPC or data providers that have enabled gRPC on their full nodes.
The online IDE provides features such as auto-completion (use Ctrl+Space or just start typing), built-in documentation (Book icon, top-left), multi-tabs, and more. You can try the example queries on this page directly in the IDE.
Supported schema
GraphQL introspection exposes the schema supported by the RPC service. The IDE's Docs pane (Book icon, top-left) and Search dialog (Cmd + K on macOS or Ctrl + K on Windows and Linux) offer a way to browse introspection output interactively.
Consult the GraphQL reference for full documentation on the supported schema. The official GraphQL introspection documentation provides an overview on introspection and how to interact with it programmatically.
Headers
The service accepts the following optional HTTP request headers:
x-sui-rpc-version: Specifies which RPC version to use. Currently only one version is supported.x-sui-rpc-show-usage: Returns the response with extra query complexity information.
By default, each response contains the following HTTP response headers:
x-sui-rpc-request-id: A unique identifier for the request. This appears in application logs for debugging.x-sui-rpc-version: The version of the service that handled the request.
$ curl -i -X POST https://graphql.testnet.sui.io/graphql\
--header 'x-sui-rpc-show-usage: true' \
--header 'Content-Type: application/json' \
--data '{
"query": "query { epoch { referenceGasPrice } }"
}'
Output
HTTP/2 200
content-type: application/json
content-length: 179
x-sui-rpc-request-id: f5442058-47ab-4360-8295-61c009f38516
x-sui-rpc-version: 1.56.1-
vary: origin, access-control-request-method, access-control-request-headers
access-control-allow-origin: *
date: Tue, 09 Sep 2025 23:34:04 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{
"data": {
"epoch": {
"referenceGasPrice": "1000"
}
},
"extensions": {
"usage": {
"input": {
"nodes": 2,
"depth": 2
},
"payload": {
"query_payload_size": 67,
"tx_payload_size": 0
},
"output": {
"nodes": 2
}
}
}
}
Variables
Variables offer a way to introduce dynamic inputs to a re-usable or static query. Declare variables in the parameters to a query or mutation, using the $ symbol and its type (in this example Int), which must be a scalar, enum, or input type. In the query body, refer to it by its name prefixed with the $ symbol.
If you declare a variable but don't use it, or define it in the query, the query fails to execute. To learn more, read the GraphQL documentation on variables.
In the following example, a variable supplies the ID of the epoch being queried:
query ($epochID: Int) {
epoch(id: $epochID) {
referenceGasPrice
}
}
Variables:
{
"epochID": 100
}
Within the GraphQL IDE
When using the GraphQL online integrated development environment (IDE), supply variables as a JSON object to the query in the Variables pane at the bottom of the main editing window. You receive a warning if you supply a variable but don't declare it.
Within requests
When making a request to the GraphQL service using a tool such as curl, pass the query and variables as two fields of a single JSON object:
$ curl -X POST https://sui-testnet.mystenlabs.com/graphql \
--header 'Content-Type: application/json' \
--data '{
"query": "query ($epochID: Int) { epoch(id: $epochID) { referenceGasPrice } }",
"variables": { "epochID": 100 }
}'
Fragments
Fragments are reusable units that you can include in queries as needed. To learn more, consult the official GraphQL documentation. The following example uses fragments to factor out a reusable snippet representing a Move value:
query DynamicField {
object(
address: "0xb57fba584a700a5bcb40991e1b2e6bf68b0f3896d767a0da92e69de73de226ac"
) {
dynamicField(
name: {
type: "0x2::kiosk::Lock",
bcs: "NLArx1UJguOUYmXgNG8Pv8KbKXLjWtCi6i0Yeq1Vhfw=",
}
) {
...DynamicFieldSelect
}
}
}
fragment DynamicFieldSelect on DynamicField {
name {
...MoveValueFields
}
value {
...DynamicFieldValueSelection
}
}
fragment DynamicFieldValueSelection on DynamicFieldValue {
__typename
... on MoveValue {
...MoveValueFields
}
... on MoveObject {
hasPublicTransfer
contents {
...MoveValueFields
}
}
}
fragment MoveValueFields on MoveValue {
type {
repr
}
json
bcs
}
Pagination
GraphQL supports queries that fetch multiple kinds of potentially nested data. For example, the following query retrieves the first 10 transactions in epoch 97 along with the digest, sender's address, gas object returned after paying for the transaction, gas price, and gas budget:
query {
epoch(epochId: 97) {
transactions(first: 10) {
pageInfo {
hasNextPage
endCursor
}
nodes {
digest
sender {
address
}
effects {
gasEffects {
gasObject {
address
}
}
}
gasInput {
gasPrice
gasBudget
}
}
}
}
}
If there are too many transactions to return in a single response, the service applies a limit on the maximum page size for variable size responses (like the transactionBlock query) and you must fetch further results through pagination.
Connections
Fields that return a paginated response accept the following optional parameters:
first: Limit on page size that is met by dropping excess results from the end.after: Cursor that bounds the results from below, exclusively.last: Limit on page size that is met by dropping excess results from the start.before: Cursor that bounds the results from above, exclusively.
They also return a type that conforms to the GraphQL Cursor Connections Specification, meaning its name ends in Connection, and it contains at minimum the following fields:
pageInfoof type PageInfo, which indicates whether there are more pages before or after the page returned.nodes: The content of the paginated response as a list of the type being paginated (TransactionBlockin the previous example).edges: Similar tonodesbut associating each node with its cursor.
Cursors
Cursors are opaque identifiers for paginated results. The only valid source for a cursor parameter (like after and before) is a cursor field from a previous paginated response (like PageInfo.startCursor, PageInfo.endCursor, or Edge.cursor). The underlying format of the cursor is an implementation detail, and is not guaranteed to remain fixed across versions of the GraphQL service, so do not rely on it. Generating cursors out of thin air is not expected or supported.
Cursors are used to bound results from below (with after) and above (with before). In both cases, the bound is exclusive, meaning it does not include the result that the cursor points to in the bounded region.
Consistency
Cursors for queries that paginate live objects also guarantee consistent pagination. They encode the checkpoint at which the query was first executed so that later pages are scoped by the same checkpoint, even if newer checkpoints are available. If both an after and a before cursor are provided, they must both be from the same checkpoint, otherwise the query produces an error.
By default, RPCs offer roughly 1 hour of retention for consistent pagination.
Page limits
After results are bounded using cursors, a page size limit is applied using the first and last parameters. The service requires these parameters to be less than or equal to the max page size limit, and if you provide neither, it selects a default. In addition to setting a limit, first and last control where excess elements are discarded from. For example, if there are 10 potential results (R0, R1, through R9) after cursor bounds have been applied, then:
- A limit of
first: 3would selectR0,R1,R2. - A limit of
last: 3would selectR7,R8,R9.
It is an error to apply both a first and a last limit.
Scope
GraphQL requests are evaluated in a scope that controls the checkpoint being viewed. The GraphQL service responds to queries as if this is the last checkpoint to have been executed. By default, this is set to the latest checkpoint that the service has all data for. To avoid returning partial responses, the service does not allow queries to specify a later checkpoint than this, but it can be set to an earlier checkpoint to perform historical queries.
Optionally, the scope provides a root object bound that applies only to queries that fetch dynamic fields. The query fetches dynamic fields as they existed at the end of a specific checkpoint or when their root object reached a given version. For any wrapped or child (object-owned) object, the root object is defined recursively as:
- The root object of the object it is wrapped in, if it is wrapped
- The root object of its owner, if it is owned by another object
- The object itself
If a dynamic field's root object has version v, its own version, w is the latest version such that w <= v meaning the latest version of the dynamic field that existed when its root object was at version v.
If a root object bound is not provided, dynamic fields are fetched at the checkpoint being viewed, while if a checkpoint-based root object bound exists, it does not impact the checkpoint being viewed.
Finally, the GraphQL service treats queries nested under executed Mutation.executeTransaction and simulated Query.simulateTransaction transactions as being in a special scope that exists just after the transaction that was executed or simulated, without having indexed that transaction.
The scope a query is evaluated in impacts which fields are available. In particular:
- Live object set queries are not available under executed transaction scopes or when a root object binding specifies a particular version. These queries rely on data that is indexed at the checkpoint level.
- Queries that paginate through history are not available under executed transaction scopes. Before indexing occurs, the system cannot determine where in the history the transaction falls.
Setting checkpoint scope
You can run queries against a historical checkpoint using Checkpoint.query. For consistent live object set queries (such as fetching an address' owned objects or balances, or an object's dynamic fields), you can continue to paginate using a cursor obtained from a previous query at that checkpoint.
query AtCheckpoint($cp: UInt53!) {
checkpoint(sequenceNumber: $cp) {
query {
transactions(last: 5) {
nodes {
digest
}
}
}
}
}
query NextBalancesPage($address: SuiAddress!, $after: String!) {
address(address: $address) {
balances(after: $after, first: 10) {
pageInfo {
hasNextPage
endCursor
}
nodes {
objectId
balance
}
}
}
}
AtCheckpoint returns the last 5 transactions to execute as of the end of the checkpoint with sequence number $cp, while NextBalancesPage fetches the next 10 balances for $address after the page that ended at cursor $after. You can also combine both approaches, to ensure that the first page of a live object query is fetched from a specific checkpoint:
query FirstBalancesPageAtCheckpoint($address: SuiAddress!, $cp: UInt53) {
checkpoint(sequenceNumber: $cp) {
query {
address(address: $address) {
balances(first: 10) {
pageInfo {
hasNextPage
endCursor
}
nodes {
objectId
balance
}
}
}
}
}
}
Responses to these queries are subject to retention. If $cp is outside the retention window Query.transactions, AtCheckpoint returns no results, while an attempt to continue paginating NextBalancesPage at a checkpoint outside the consistent range returns an error.
Setting root version scope
Queries nested under the fetch of an object at a specific version are scoped by a root object bound at its version. For example, in the following query, the dynamic field with name 42u64 is fetched as it existed when its owning object was at version $v:
query ObjectsDynamicFields($id: SuiAddress!, $v: UInt53!) {
object(address: $id, version: $v) {
dynamicField(name: { literal: "42u64" }) {
value {
... on MoveValue {
json
}
}
}
}
}
This property applies recursively to nested dynamic field queries. It also applies if the root object is fetched at a specific checkpoint using the atCheckpoint parameter or at the latest checkpoint (by omitting all parameters). In these cases, the root object bound is checkpoint-based.
The rootVersion parameter overrides this implicit bound. It fetches the object as if it was subject to a root version bound governed by the parameter, which also applies to queries nested underneath it. This is necessary when fetching a dynamic field directly (as an object), because an object's version is not updated when its children are updated unless it is a root object.
In the following query, $id is the address of a dynamic field fetched as it existed when its root object was at version $r. The nested query fetches a nested dynamic field with name 42u64 owned by a wrapped object stored in field foo of the dynamic field. The nested fetch is subject to the same root object version bound, $r.
query NestedDynamicFields($id: SuiAddress!, $r: UInt53!) {
object(address: $id, rootVersion: $v) {
asMoveObject {
asDynamicField {
value {
... on MoveValue {
extract(path: "foo->[42u64]") {
json
}
}
}
}
}
}
}
Queries that return an Address can be used to make nested dynamic field queries on wrapped objects. An Address does not have an associated version, but Query.address can accept rootVersion or atCheckpoint parameters to set root object bounds for nested dynamic field queries. The following query fetches a dynamic field with name 42u64 owned by an object with address $id (which can belong to a wrapped object) as it existed when its root object was at version $r:
query WrappedDynamicField($id: SuiAddress!, $r: UInt53!) {
address(address: $id, rootVersion: $r) {
dynamicField(name: { literal: "42u64" }) {
value {
... on MoveValue {
json
}
}
}
}
}
While nested within a scope that has a root object bound, you can reset or override the bound using the objectAt or addressAt queries. These fields query the same entity but at a different position in its history. If these fields are not provided any parameters, they fetch the state of the object at the latest known checkpoint to the GraphQL service. The following query fetches the latest version of an object that was previously fetched at version $v:
query LatestDynamicField($id: SuiAddress!, $v: UInt53!) {
object(address: $id, version: $v) {
objectAt {
version
}
}
}
Limits
The GraphQL service for Sui RPC is rate-limited on all available instances to keep network throughput optimized and to protect against excessive or abusive calls to the service.
Rate limits
Queries are rate-limited at the number of attempts per minute to ensure high availability of the service to all users.
Query limits
In addition to rate limits, queries are also validated against a number of rules on their complexity, such as the number of nodes, the depth of the query, or their payload size. Query the serviceConfig field to retrieve these limits. An example of how to query for some of the available limits follows:
{
serviceConfig {
maxQueryDepth
maxQueryNodes
maxOutputNodes
defaultPageSize(type: "Query", field: "transactions")
maxPageSize(type: "Query", field: "objects")
queryTimeoutMs
maxQueryPayloadSize
maxTypeArgumentDepth
maxTypeArgumentWidth
maxTypeNodes
maxMoveValueDepth
}
}
Rich queries
Rich queries require a dedicated request to a backing store. There is a limit on the number of rich queries you can perform in a single GraphQL request, which can also be queries from the serviceConfig:
{
serviceConfig {
maxRichQueries
}
}
If a request performs more rich queries than the allowed limit, excess rich queries are arbitrarily replaced by a "RESOURCE_EXHAUSTED" error. Rich queries include:
- Paginating owned object queries, such as
IAddressable.objects,IAddressable.balances, andIMoveObject.dynamicFields. - Paginating historical queries, such as
Query.transactions, andQuery.events. - Paginating through versions of packages and objects, such as
Query.objectVersions,IObject.objectVersionsAfter, orIObject.objectVersionsBefore.
Retention
Different queries are subject to their own retention policies. In the vanilla, general purpose setup, live object set queries work only for recent checkpoints (measured in minutes or hours), while transaction pagination may be available only back to certain checkpoints (measured in weeks or months), depending on the filters applied. Data outside these ranges is pruned.
Data source retention
GraphQL queries rely on different data sources with different retention ranges:
| Data source | Examples | Typical retention |
|---|---|---|
| Consistent store | Query.objects, Address.balance, objects by owner or type | ~1 hour |
| Database store | Query.transactions, Query.events, Query.checkpoints | ~(30-90) days |
| Archival service | Point lookups (transaction by digest, object by ID and version) | Indefinite (if configured) |
Retention is dependent on the pruning policies of datasource pipelines configured by the stack operator. For production configuration examples, see Indexer Stack Setup.
Querying available range
Query the available checkpoint range using serviceConfig.availableRange:
availableRange(type: String!, field: String, filters: [String!]): AvailableRange!
type: The GraphQL type name, such as"Query"or"Address".field: The field on that type, such as"transactions"or"events".filters: Filter field names from the filter input type, such as["affectedAddress"]forTransactionFilter,["module"]forEventFilter, or direct query parameter names like["version"].
Match your query parameters to filter names: if your query uses filter: { affectedAddress: "0x..." }, pass filters: ["affectedAddress"].
Datasource pipelines can be configured with different retention ranges based on pruning configurations. When multiple filters are passed to the available range query, the strictest retention range of the pipelines that support the filters is returned.
Examples
# Check available range for transaction queries filtered by affected address
{
serviceConfig {
availableRange(type: "Query", field: "transactions", filters: ["affectedAddress"]) {
first {
sequenceNumber
}
last {
sequenceNumber
}
}
}
}
# Check available range for a checkpoint transactions queries filtered by affected object
{
serviceConfig {
availableRange(type: "Checkpoint", field: "Transactions", filters: ["affectedObject"]) {
first {
sequenceNumber
}
last {
sequenceNumber
}
}
}
}
Each field in a nested query has its own retention limit:
query {
address(address: "0x...") {
# Uses Consistent Store (~1 hour retention)
dynamicFields(first: 10) {
nodes {
value {
... on MoveObject {
# Uses DB Store (may have different retention)
objectAt(checkpoint: 10579000) {
version
}
}
}
}
}
}
}
Use serviceConfig.availableRange to check retention for each field separately.
Handling "Outside available range" errors
If you encounter an error indicating data is outside the available range, it means your query is requesting data that has been pruned. To resolve this:
- Check the available range first using
serviceConfig.availableRangebefore starting long pagination runs. - Use fresh cursors. Old cursors may reference checkpoints that have since been pruned.
- Adjust your query bounds. Ensure
afterCheckpoint/beforeCheckpointfilters fall within the available range.
Example queries
The following queries show some common tasks you can perform with GraphQL.
Find the reference gas price for latest epoch
query {
epoch {
referenceGasPrice
}
}
Find a specific historical epoch
Find the total stake rewards, the reference gas price, the number of checkpoints, and the total gas fees for epoch 100. In the query, the epochId argument is optional and defaults to the latest epoch.
query {
epoch(epochId: 100)
{
epochId
totalStakeRewards
referenceGasPrice
totalCheckpoints
totalGasFees
totalStakeSubsidies
storageFund {
totalObjectStorageRebates
nonRefundableBalance
}
}
}
Find a transaction by its digest
Get a transaction by its digest and show information such as the gas sponsor address, the gas price, the gas budget, and the effects from executing that transaction.
query {
transaction(digest: "FdK...qK2") {
gasInput {
gasSponsor {
address
}
gasPrice
gasBudget
}
effects {
status
timestamp
checkpoint {
sequenceNumber
}
epoch {
epochId
referenceGasPrice
}
}
}
}
Find the last 10 transactions that are not a system transaction
query {
transactions(last: 10, filter: {kind: PROGRAMMABLE_TX}) {
nodes {
digest
kind {
__typename
}
}
}
}
Find all transactions that touched a given object
Find all the transactions that touched (modified, transferred, or deleted) a given object. This might be useful when you want to trace the flow of a Coin, StakeSui, NFT, or similar object.
This example uses GraphQL variables and pagination.
query ($objectID: SuiAddress!) {
transactions(filter: {affectedObject: $objectID}) {
nodes {
sender {
address
}
digest
effects {
objectChanges {
nodes {
address
}
}
}
}
}
}
Variables
When using the online IDE, copy the following JSON to the Variables window, below the main editor.
{
"objectID": "0x11c6ae8432156527fc2e12e05ac7db79f2e972510a823a4ef2e670f27ad7b52f"
}
Filter transactions by a function
Find the last 10 transactions that called the public_transfer function as a Move call transaction command.
This example makes use of the last filter. In this case, it returns only the last 10 transactions known to the service.
{
transactions(
last: 10,
filter: {
function: "0x2::transfer::public_transfer"
}
) {
nodes { digest }
}
}
Find transaction balance changes
Find the balance changes of all the transactions where a given address called a staking-related function. This might be useful when you want to get your staking or unstaking history.
query ($address: SuiAddress!) {
transactions(filter: {
function: "0x3::sui_system::request_add_stake"
sentAddress: $address
}) {
nodes {
digest
effects {
balanceChanges {
nodes {
owner {
address
}
amount
}
}
}
}
}
}
Variables
When using the online IDE, copy the following JSON to the Variables window, below the main editor.
{
"address": "0xa9ad44383140a07cc9ea62d185c12c4d9ef9c6a8fd2f47e16316229815862d23"
}
Fetch a dynamic field on an object
This example uses aliases and fragments.
query DynamicField {
object(
address: "0xb57fba584a700a5bcb40991e1b2e6bf68b0f3896d767a0da92e69de73de226ac"
) {
dynamicField(
name: {
type: "0x2::kiosk::Lock",
bcs: "NLArx1UJguOUYmXgNG8Pv8KbKXLjWtCi6i0Yeq1Vhfw=",
}
) {
...DynamicFieldSelect
}
}
}
fragment DynamicFieldSelect on DynamicField {
name {
...MoveValueFields
}
value {
...DynamicFieldValueSelection
}
}
fragment DynamicFieldValueSelection on DynamicFieldValue {
__typename
... on MoveValue {
...MoveValueFields
}
... on MoveObject {
hasPublicTransfer
contents {
...MoveValueFields
}
}
}
fragment MoveValueFields on MoveValue {
type {
repr
}
json
bcs
}
Fetch all dynamic fields on an object
Paginate over the dynamic fields of an object. It can be used for iterating over the elements of on-chain data structures, like tables and bags. See The Move Book to learn more about dynamic collections available in Move.
query ($id: SuiAddress!) {
address(address: $id) {
dynamicFields {
nodes {
name { ...Value }
value {
__typename
... on MoveValue {
...Value
}
... on MoveObject {
contents {
...Value
}
}
}
}
}
}
}
fragment Value on MoveValue {
type {
repr
}
json
}
Paginate checkpoints forward
Set up a paginated query starting at the genesis checkpoint, reading 5 checkpoints at a time in increasing order of sequence number. The value of pageInfo.hasNextPage determines whether there is another page to read. The value of pageInfo.endCursor is used as the cursor to read $after.
This example uses GraphQL variables and pagination.
query ($after: String) {
checkpoints(first: 5, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
digest
timestamp
}
}
}
Paginate checkpoints backwards
Set up a paginated query starting at the latest indexed checkpoint, reading 5 checkpoints at a time in decreasing order of sequence number. The value of pageInfo.hasPreviousPage determines whether there is another page to read. The value of pageInfo.startCursor is used as the cursor to read $before.
This example uses GraphQL variables and pagination.
query ($before: String) {
checkpoints(last: 5, before: $before) {
pageInfo {
hasPreviousPage
startCursor
}
nodes {
digest
timestamp
}
}
}
Execute a transaction
Transaction execution takes 2 arguments, transactionDataBcs and signatures. transactionDataBcs is the serialized unsigned transaction data, which the Sui Client CLI client call command can generate. Pass the --serialize-unsigned-transaction flag to the command to call a Move function. The Sui Keytool CLI command sui keytool sign can generate the signatures.
mutation ($tx: String!, $sigs: [String!]!) {
executeTransaction(transactionDataBcs: $tx, signatures: $sigs) {
errors
effects {
status
epoch {
startTimestamp
}
gasEffects {
gasSummary {
computationCost
}
}
}
}
}
Variables
When using the online IDE, copy the following JSON to the Variables window, below the main editor.
{
"tx": "AAACACAZXApmrHgzTs3FGDyXWka+wmMCy2IwOdKLmTWHb5PnFQEASlCnLAw4qfzLF3unH9or5/L7YpOlReaSEWfoEwhTqpavSxAAAAAAACCUFUCOn8ljIxcG9O+CA1bzqjunqr4DLDSzSoNCkUvu2AEBAQEBAAEAALNQHmLi4jgC5MuwwmiMvZEeV5kuyh+waCS60voE7fpzAa3v/tOFuqDvQ+bjBpKTfjyL+6yIg+5eC3dKReVwghH/rksQAAAAAAAgxtZtKhXTr1zeFAo1JzEqVKn9J1H74ddbCJNVZGo2I1izUB5i4uI4AuTLsMJojL2RHleZLsofsGgkutL6BO36c+gDAAAAAAAAQEIPAAAAAAAA",
"sigs": [
"AB4ZihXxUMSs9Ju5Cstuuf/hvbTvvycuRk2TMuagLYNJgQuAeXmKyJF9DAXUtL8spIsHrDQgemn4NmojcNl8HQ3JFqhnaTC8gMX4fy/rGgqgL6CDcbikawUUjC4zlkflwg=="
]
}
Migrating to GraphQL from JSON-RPC
The examples in the following sections are tabbed to show both the JSON-RPC call and the equivalent GraphQL structure. For a comprehensive list of all available GraphQL features, consult the reference.
Example 1: Get total transactions
Get the total number of transactions in the network.
- JSON-RPC
- GraphQL
{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getTotalTransactionBlocks",
"params": []
}
query {
checkpoint {
networkTotalTransactions
}
}
Example 2: Get a specific transaction
Get the transaction by its digest.
- JSON-RPC
- GraphQL
{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getTransactionBlock",
"params": [
"Hay2tj3GcDYcE3AMHrej5WDsHGPVAYsegcubixLUvXUF",
{
"showInput": true,
"showRawInput": false,
"showEffects": true,
"showEvents": true,
"showObjectChanges": false,
"showBalanceChanges": false
}
]
}
query {
transaction(digest: "Hay2tj3GcDYcE3AMHrej5WDsHGPVAYsegcubixLUvXUF") {
gasInput {
gasSponsor {
address
}
gasPrice
gasBudget
}
effects {
status
timestamp
checkpoint {
sequenceNumber
}
epoch {
epochId
referenceGasPrice
}
}
}
}
Example 3: Get coin objects owned by an address
Return all Coin<0x2::sui::SUI> objects that an address owns.
- JSON-RPC
- GraphQL
query {
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getCoins",
"params": [
"0x5094652429957619e6efa79a404a6714d1126e63f551f4b6c7fb76440f8118c9", //owner
"0x2::sui::SUI", //coin type
"0xe5c651321915b06c81838c2e370109b554a448a78d3a56220f798398dde66eab", //cursor
3 //limit
]
}
query {
address(address: "0x5094652429957619e6efa79a404a6714d1126e63f551f4b6c7fb76440f8118c9") {
objects(
first: 3,
after: "vBIzCwAAAADMAQBQlGUkKZV2Gebvp5pASmcU0RJuY/VR9LbH+3ZED4EYyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAARjb2luAAAAAAAAAARDb2luAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAA3N1aQAAAAAAAAADU1VJAAAAAAAAAAAB/////XBZUf9feyhb9cW+AOBraL10O9t0D9JAr+tIq2wXDJdl5/zP5w==",
filter: { type: "0x2::coin::Coin<0x2::sui::SUI>" }
) {
nodes {
address
}
}
}
}
The cursor is now passed in the after (or before) fields on the connection, and the limit in the first or last fields.
There is functionality available to GraphQL that can't be replicated with JSON-RPC, such as:
-
Time travel queries with checkpoint
{ query { ... } }. -
Nested dynamic field look-ups (and paginating dynamic fields with their contents in 1 request).
-
Fetching live objects by owner kind and type (such as all shared objects of a certain type).
-
Fetching deserialized input and output object contents from a transaction that has just executed.
The following examples demonstrate some of the functions not available with JSON-RPC.
Example 4: Getting objects by type
Fetch the latest versions of objects of type 0x2::package::Publisher that are currently live on-chain.
query {
objects(filter: { type: "0x2::package::Publisher" }) {
nodes {
address
digest
asMoveObject {
contents { json }
}
}
}
}
Example 5: Paging through package versions
Find all versions of the Sui framework and list their modules:
query {
packageVersions(address: "0x2") {
nodes {
version
modules {
nodes {
name
}
}
}
}
}
Related links
GraphQL is a public service for the Sui RPC that enables you to efficiently interact with the Sui network.
Setup instructions for running the indexer, consistent store, and GraphQL in production.
Operate a Sui full node to validate blockchain activities, like transactions, checkpoints, and epoch changes.
Sui GraphiQL IDE for Testnet (Public good).
Sui GraphiQL IDE for Mainnet (Public good).