Launching Sui GraphQL RPC Service

We’re happy to announce the launch of the Sui GraphQL RPC service, as part of our ongoing efforts to provide the best web3 infrastructure and developer experience. This MVP is available for mainnet and testnet networks.

Getting Started

Mainnet online IDE: https://sui-mainnet.mystenlabs.com/graphql

Testnet online IDE: https://sui-testnet.mystenlabs.com/graphql

Documentation:

The online IDE provides an interactive experience by offering auto-completion (use Ctrl+Space) and in-built documentation (click on the book-like icon on the top left). The Getting Started documentation has a number of examples that you can use to get started. Note that any addresses or object IDs in the examples correspond to the mainnet data.

Upcoming Breaking Changes

Please note that we expect to be landing breaking changes to the schema on most of the upcoming major releases (every 3 months), while we’re continuing the development and improvements for this service.

Releases and Timeline

The first version of RPC 2.0 is released as 2024-1.0. This version of the RPC supports all MVP features in the proposed schema and it is deployed by Mysten Labs and shared with third-party RPC providers for integration into their services.

There will be two types of releases: major (every 3 months), and minor (every 2 weeks with bug-fixes). Major releases will be announced and will likely contain breaking changes. The next major release is at the end of Q1’24. In between major releases, we will have patch releases every two weeks.

Each RPC major version will receive 6 months of support for bugfixes. Publicly available Mysten-operated RPC instances will also continue to provide access to an RPC version for 6 months after its initial release. Clients that continue to use versions older than 6 months will be automatically routed to the oldest supported version by the public Mysten RPC instances. E.g. clients who continue to use 2023-10.x past the release of 2024-04.y will automatically be served responses by 2024-01.z to limit the number of versions an RPC provider needs to support.

Setting Versions

API versions can be supplied as a header, not including the patch version (e.g. X-Sui-RPC-Version: 2023.10). If a header is not supplied, the latest released version is assumed.
The response header will include the full version used to respond to the request, including the patch version (e.g. X-Sui-RPC-Version: 2023.10.2).

Feedback

We welcome feedback that you have, particularly about performance issues, so please post it in this thread.

Disclaimer & Limitations

Please note that this service is offered as is, without a SLA.

The endpoint is rate-limited to avoid congestion and misuse (this service is not intended for production) and it does have some limits on the complexity of the queries one can make. Please use this query to find the current rate limits on the GraphQL queries:

{
  serviceConfig {
    maxQueryDepth
    maxQueryNodes
    maxOutputNodes
    maxDbQueryCost
    defaultPageSize
    maxPageSize
    requestTimeoutMs
    maxQueryPayloadSize
    maxTypeArgumentDepth
    maxTypeArgumentWidth
    maxTypeNodes
    maxMoveValueDepth
  }
}

By default, there is a query timeout of 15s. If the time limit is exceeded, the query is stopped and an error is returned.

There are a few unsupported features and/or limitations for this MVP launch:

  • Subscriptions are not supported.
  • Queries requesting stake related information might be a bit slower or fail the first time, depending on an internal cache. If it fails, try again after a couple of minutes.
  • Some performance optimizations are still in progress, thus some queries may be slower than expected. Please let us know if you encounter such issues.
  • Consistency between queries for disparate fields in the same GraphQL request are a work in progress, so there may be some rare opportunities for inconsistencies to appear in such cases.

CHANGELOG

Bug Fixes

  • Fixed the order in which transaction blocks were returned when paginating backwards.
    #15661
  • Fixed bugs where the lamport version for object changes would incorrectly report null.
    #15040

Breaking Changes

Pagination

Fields that return variable length output have been systematically refactored:

  • Fields that were already paginated have been renamed to remove the Connection suffix from their name (e.g. coinConnection becomes coins), but not their type (coins still returns a CoinConnection).
  • Cursor values are now all obfuscated.
  • Paginated fields now all support forward and backward pagination, with accurate previous an next page detection.
  • Fields that previously returned arrays have been updated to return a paginated response.

#15933, #15782, #15749, #15721, #15712, #15661, #15528, #15586, #15526, #15525, #15524, #15485, #15484, #15475, #15474, #15473, #15472, #15471, #15470, #15467

Additionally, the service enforces a new “output node estimate” limit, which calculates an estimate of how large the query output will be (accounting for page limits on paginated fields), and enforces a limit on this.

#15497, #15492

Removal of Explicit Upcasts

Operations that offered explicitly upcasts, such as Coin.asMoveObject, MoveObject.asObject, etc have been replaced by interfaces that allow the user to query fields from MoveObject on its sub-types (like Coin). The newly introduced interfaces are:

  • IOwner
  • IObject
  • IMoveObject

These interfaces are cascading, so a Coin implements all three, and can access fields on MoveObject, Object, and Owner without explicitly upcasting to them.

#15825

Epoch and System State

  • The last Checkpoint in the epoch no longer exposes EndOfEpochData – this information is exposed via Epoch instead.
    #15522
  • SystemStateSummary has been merged into Epoch.
    #15489

Transactions

  • Removed the SENT and PAID enum variants from AddressTransactionBlockRelationship, to be added back when their associated queries can be implemented efficiently.
    #15661
  • The sender field for TransactionBlock and Event will now return null if the transaction in question was sent by the system (instead of 0x0).
    #15580, #15147
  • Simplified TransactionBlock.signatures to be just a Base64 blob, and not a dedicated type with a single Base64 field.
    #15145
  • Improved the format for TransactionBlockEffects.errors, to be more human readable.
    #15039

Cascading Filters

Filters, like ObjectFilter, EventFilter, and TransactionBlockFilter that included constraints on modules and types have collapsed the fields relevant to those queries into
one.

For example, EventFilter.eventPackage, EventFilter.eventModule, EventFilter.eventType have been replaced with a single EventFilter.eventType filter, that expects one of the following formats:

  • package, matching all types in the package.
  • package::module, matching all types in the module.
  • package::module::Type, matching the type or all type instantiations of the type.
  • package::module::Type<TypeParams, ...>, matching a specific type instantiation.

#15712, #15661, #15303, #15200

Filter Intersection

Previously, in the case of nested queries, where the filter in the nested query conflicted with a filter implied by its context, the filter implied by the context would override the inner filter:

query {
  address(address: "X") {
    transactionBlocks(filter: { signAddress: "Y" }) {
      nodes { digest }
    }
  }
}

This behavior has been changed so that such that filters are always intersected. This means the above query would return no results, rather than ignore the signAddress filter parameter.

#15712, #15661

Renamed Fields

Various field names have been revised in response to feedback during RPC 1.5:

  • IOwner.defaultNameServiceName has been renamed to defaultSuinsName.
    #15761
  • Query.resolveNameServiceAddress has been renamed to resolveSuinsName.
    #15760
  • Event.senders has been renamed to Event.sender as a transaction can currently only have one sender.
    #15580
  • A number of fields have been renamed to use camelCase formatting: queryPayload (show-usage extension), typeParameters in various Move Type-related scalars.
    #15574
  • References to struct in type definitions, signatures, etc have been renamed to datatype in preparation for enum support in Move.
    #15549
  • Checkpoint.validatorSignature has been renamed to Checkpoint.validatorSignatures as it contains multiple signatures.
    #15522
  • StakedSui.activeEpoch and StakedSui.requestEpoch were renamed to past tense.
    #15329
  • Renamed location to address, everywhere.
    #15196

Object Ownership

  • IOwner.objects now returns pages of MoveObjects, rather than Object, because MovePackages are immutable and therefore not owned by any other entity.
    #15804
  • Object.kind and Object.owner have been merged into a single IObject.owner field that specifies whether an object is address-owned, immutable, shared, or a child object, and based on context, also includes the owner address/object or the initial shared version in case of shared objects.
    #15569

Error codes

Certain user errors, related to input parsing issues no longer produce an error code indicating that the issue is a user error. This is a known issue which will be addressed in a future patch
release. This issue affects the parsing of SuiNS domains, types, type filters, and Base58 digests.

#15781, #15760, #15749, #15527

Directives

Unrecognized directives will cause the request to produce an error. The GraphQL service explicitly supports the @skip and @include directives.

#15570, #15124

New Features

Transaction Execution

  • Implemented Mutation.executeTransactionBlock as per the proposed schema.
    #15820, #15118
  • Implemented Query.dryRunTransactionBlock. The epoch parameter has been removed from this API as it was not used downstream.
    #15717

Historical Reads and Consistency

  • TransactionBlock.gasPayments returns the gas objects at the version they were used as payment, not their latest version.
    #15721
  • Object queries that filter on version can now access historical data, for a limited window of time (the available range), as opposed to always returning the latest versions of objects.
    #15967, #15958, #15963, #15932, #15931, #15915, #15914
  • Implemented consistent pagination: Fetching further pages for a paginated response will continue to return results from the state of the chain at the point the first page was fetched, and will not reflect changes that were indexed in more recent checkpoints, as long as the checkpoint at the start of the range remains in the available range (5 to 15 minute historical window).
    #16006, #15996, #15962, #15961, #15960, #15959

Epoch

  • Added per-epoch stats (checkpoint count, gas fees, stake rewards and subsidies).
    #14979
  • Moved liveObjectDigest from Checkpoint to Epoch. #15993
  • Implemented totalTransactions. #15993

MoveObject

  • Implemented asSuinsRegistration to attempt to downcast a MoveObject to a SuinsRegistration.
    #15760

MovePackage

  • Removed MoveModuleId replaced systematically with MoveModule.
    #15020
  • Implemented MoveModule according to draft schema.
    #15018, #15016, #15015, #15013
  • Implemented MoveStruct according to draft schema.
    #14974

MoveType

  • Included type information for structs in type layouts.
    #15409
  • Implemented abilities field that exposes the concrete abilities of a given type.
    #15407

MoveValue

  • Special case the representation 0x2::object::ID to match the representation of UID and address in the JSON representation of Move Values.
    #15408

Object

  • Implemented receivedTransactionBlocks, which is similar to Address.transactionBlocks but specialised to only fetch the transactions that sent objects to this object (as objects cannot sign transactions).
    #15823
  • Implemented support for the ObjectFilter.objectKeys filter to filter for objects of a specific version.
    #15712
  • Implemented display.
    #15391

Owner

  • Implemented asObject to attempt to downcast an Owner (which could be an object or an address), to an object.
    #15826
  • Implements suinsRegistrations to list the SuiNS Registration NFTs owned by an entity.
    #15390

Query

  • Implemented availableRange which indicates what range of checkpoints the indexer can produce consistent results for.
    #15460, #15219
  • Implemented type query to look-up information about a particular concrete type (layout, abilities, etc).
    #15278

ServiceConfig

  • Exposed maxOutputNodes
    #15492
  • Exposed limits related to type resolution.
    #15442
  • Exposed defaultPageSize limit, a new configuration distinct from maxPageSize.
    #15009, #15000

Stake

TransactionBlock

TransactionBlockEffects

  • Implemented support for TransactionBlockEffects.events.
    #15429
  • Implemented unchangedSharedObjects to view the shared objects that were read but not modified by the transaction.
    #15269

Validator

  • Implemented apy field, whose type was changed from Float to Int (basis points).
    #15173

ValidatorSet

  • Implemented pendingActiveValidatorsId, stakingPoolMappingsId, inactivePoolsId, validatorCandidatesId. #15993
6 Likes

We have launched the GraphQL service for devnet, which will contain weekly updates from main branch of the Sui repo. This will be a cutting-edge version, so breaking changes are expected.
https://sui-devnet.mystenlabs.com/graphql

1 Like

Updates regarding the devnet release. The Sui GraphQL RPC service now supports different versions.

For example:

sui-network.mystenlabs.com/graphql/stable - use this for a stable GraphQL service running on one of the three networks: mainnet, testnet or devnet. This will receive fixes and improvements, but no GraphQL schema breaking changes, until the next major release scheduled for sometime in early Q3.

sui-devnet.mystenlabs.com/graphql/beta - use this for having access to the latest changes to the GraphQL service. This is published bi-weekly from the main branch. NB: queries might break between releases, use at your own risk. Only available for devnet.

sui-network.mystenlabs.com/graphql/legacy - use this for the legacy version of the GraphQL service. This will receive bug-fixes, but in general is kept for legacy reasons.

When you do a request, you can check the response headers (x-sui-rpc-version) to get the exact version of the service, which includes the YEAR.MONTH.PATCH version and the build SHA. For more details on versioning, check out the versioning section in this GitHub issue; (NB: note that setting the version is now done through the path to the service, and not via a header as in the original proposal).

1 Like