Sui GraphQL RPC
The GraphQL RPC service is currently under development. The MVP is scheduled to be launched at the end of January 2024.
For an introduction to GraphQL, see GitHub's Introduction to GraphQL.
Getting Started
The quickest way to access the Sui GraphQL service is through the online IDE that provides a complete toolbox for fetching data and executing transactions on the network. The online IDE provides features such as auto-completion (use Ctrl-Space or just start typing), built-in documentation (click on the top-left icon), multi-tabs, and more.
The online IDE is available for mainnet and testnet. Later in this document, you can find query examples that you can use directly in the IDE.
For more details about some concepts used in the examples below, please see the GraphQL concepts page.
Discovering the schema
GraphQL offers an introspection feature that allows you to query for the schema that is loaded by a service instance. The official documentation provides an overview on introspection.
Examples
Many examples can also be found in the repository. For example, in that folder you can find examples on transaction block effects, protocol configs, stake connection, and more. Each folder contains one or more examples that you can use in your queries.
Any existing addresses/object IDs in these examples refer to mainnet
data only.
Find the reference gas price for last epoch
query {
epoch {
referenceGasPrice
}
}
Find the stake information for epoch 100
Find the total stake rewards, the reference gas price, the number of checkpoints and the total gas fees for epoch 100. Note that in the query, the id
argument is optional. When no id is provided, it will return the data for the last known epoch.
query {
epoch(id: 100) # note that id is optional, and without it, last epoch is returned
{
epochId
totalStakeRewards
referenceGasPrice
totalCheckpoints
totalGasFees
totalStakeSubsidies
storageFund {
totalObjectStorageRebates
nonRefundableBalance
}
}
}
Find a transaction block by its digest
Get a transaction block object by its digest and show information such as the gas sponsor's address, the gas price, the gas budget, and the effects from executing that transaction block.
query {
transactionBlock(digest: "FdKFgsQ9iRrxW6b1dh9WPGuNuaJWMXHJn1wqBQSqVqK2") {
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 {
transactionBlocks(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/deleted) a given object. This is useful for when we want to trace the flow of a coin/stake/nft, and to trace the upgrade history of a package when the given object is a UpgradeCap.
Note that this example uses GraphQL variables and pagination. When using the online IDE, you need to pass the variables
in the bottom window where it's written Variables
.
query ($objectID: SuiAddress!) {
transactionBlocks(filter: {changedObject: $objectID}) {
nodes {
sender {
address
}
digest
effects {
objectChanges {
nodes {
address
}
}
}
}
}
}
where the variables are:
{
"objectID": "0x11c6ae8432156527fc2e12e05ac7db79f2e972510a823a4ef2e670f27ad7b52f"
}
Filter transaction blocks by a function
Find the last transaction blocks that called the public_transfer
function.
This example makes usage of the filter last
, which indicates that the user only wants the last 10 transaction blocks known to the service. It also uses cursors, which in this examples are used to aid for future pagination needs.
{ # Filtering by function
transactionBlocks(
last: 10,
filter: {
function: "0x2::transfer::public_transfer"
}
) {
edges { cursor }
}
}
Find the balance changes of all the transactions
Find the balance changes of all the transactions where a certain address called certain Move functions. This is useful when someone wants to get their staking and unstaking history, since you stake/unstake by calling specific Move functions.
query ($address: SuiAddress!) {
stakeTxns: transactionBlocks(filter: {
function: "0x3::sui_system::request_add_stake"
signAddress: $address
}) {
nodes {
sender {
address
}
digest
effects {
balanceChanges {
nodes {
owner {
address
}
amount
}
}
}
}
}
unstakeTxns: transactionBlocks(filter: {
function: "0x3::sui_system::request_withdraw_stake"
signAddress: $address
}) {
nodes {
sender {
address
}
digest
effects {
balanceChanges {
nodes {
owner {
address
}
amount
}
}
}
}
}
}
where address is
{
"address": "0xa9ad44383140a07cc9ea62d185c12c4d9ef9c6a8fd2f47e16316229815862d23"
}
Coins on address and its balances
This example uses aliases and fragments.
fragment C on Coin {
balance
asMoveObject {
contents { type { repr } }
}
}
{
suiCoins: coins {
edges {
cursor
node { ...C }
}
}
address(address: "0x576f3566219e81748bb599646a5f4f7317068bbe62b143518427b1977b03256d") {
coins {
edges {
cursor
node { ...C }
}
}
allBalances: balances {
edges {
cursor
node {
coinType { repr }
coinObjectCount
totalBalance
}
}
}
firstBalance: balances(first: 1) {
edges { cursor }
}
lastBalance: balances(last: 1) {
edges { cursor }
}
}
}
Find the dynamic fields of an object
query DynamicField {
object(
address: "0xb57fba584a700a5bcb40991e1b2e6bf68b0f3896d767a0da92e69de73de226ac"
) {
dynamicField(
name: {
type: "0x2::kiosk::Listing",
bcs: "NLArx1UJguOUYmXgNG8Pv8KbKXLjWtCi6i0Yeq1VhfwA",
}
) {
...DynamicFieldSelect
}
}
}
fragment DynamicFieldSelect on DynamicField {
name {
...DynamicFieldNameSelection
}
value {
...DynamicFieldValueSelection
}
}
fragment DynamicFieldNameSelection on MoveValue {
type {
repr
}
data
bcs
}
fragment DynamicFieldValueSelection on DynamicFieldValue {
... on MoveValue {
type {
repr
}
data
__typename
}
... on MoveObject {
hasPublicTransfer
contents {
type {
repr
}
data
}
__typename
}
}
Limits
The Sui GraphQL RPC service 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.
These limits can be retrieved by querying the serviceConfig
field. An example of how to query for some of the available limits (at the time of this writing) follows:
{
serviceConfig {
maxQueryDepth
maxQueryNodes
maxDbQueryCost
requestTimeoutMs
maxPageSize
maxQueryPayloadSize
}
}