본문으로 건너뛰기

GraphQL RPC 사용하기

이 가이드는 GraphQL을 사용해 Sui network를 질의하는 실용적인 예시를 제공한다. header, variable, fragment, pagination, scope, limit 같은 핵심 개념은 corresponding concepts page를 참조한다.

network에서 데이터를 가져오고 transaction을 실행하는 complete toolbox를 제공하는 온라인 IDE를 통해 Sui RPC용 GraphQL service에 접근한다:

정보

Mainnet과 Testnet service는 모두 network throughput을 최적화하기 위해 rate-limit가 적용된다. 이 service는 Sui Foundation이 공익 차원에서 제공하는 것이며 production-grade 용도를 의도하지 않는다. full node에서 gRPC를 활성화한 list of RPC or data providers를 참조한다.

온라인 IDE는 auto-completion(Ctrl+Space를 사용하거나 그냥 입력 시작), built-in 문서(Book 아이콘, 좌상단), multi-tabs 등의 기능을 제공한다. 이 페이지의 예시 query를 IDE에서 직접 시도할 수 있다.

Supported schema

GraphQL introspection은 RPC service가 지원하는 schema를 노출한다. IDE의 Docs pane(Book 아이콘, 좌상단)과 Search dialog(macOS에서는 Cmd + K, Windows와 Linux에서는 Ctrl + K)는 introspection 출력을 대화형으로 탐색하는 방법을 제공한다.

지원되는 schema에 대한 전체 문서는 Sui RPC용 GraphQL (베타)를 참조한다. official GraphQL introspection documentation는 introspection 개요와 이를 프로그래밍 방식으로 다루는 방법을 제공한다.

Headers

service는 다음 optional HTTP request header를 받는다:

  • x-sui-rpc-version: 사용할 RPC version을 지정한다. 현재는 하나의 version만 지원된다.
  • x-sui-rpc-show-usage: extra query complexity 정보를 포함한 응답을 반환한다.

기본적으로 각 응답에는 다음 HTTP response header가 포함된다:

  • x-sui-rpc-request-id: request의 고유 식별자이다. debugging을 위해 application log에 나타난다.
  • x-sui-rpc-version: request를 처리한 service의 version이다.
$ 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 } }"
}'
Click to open
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는 재사용 가능하거나 정적인 query에 동적인 입력을 도입하는 방법을 제공한다. query 또는 mutation의 parameter에 $ symbol과 그 type(이 예시에서는 Int)을 사용해 variable을 선언하며, 이 type은 scalar, enum, input type 중 하나여야 한다. query body에서는 $ symbol이 붙은 이름으로 이를 참조한다.

variable을 선언하고도 사용하지 않거나 query 안에 정의하지 않으면 query 실행에 실패한다. 자세한 내용은 GraphQL 문서의 variables를 읽는다.

다음 예시에서는 variable이 질의하는 epoch의 ID를 제공한다:

query ($epochID: Int) {
epoch(id: $epochID) {
referenceGasPrice
}
}

Variables:

{
"epochID": 100
}

Within the GraphQL IDE

GraphQL online integrated development environment (IDE)를 사용할 때는 main editing window 아래 Variables pane에 query용 JSON object로 variable을 제공한다. variable을 제공했지만 선언하지 않으면 경고를 받는다.

Within requests

curl 같은 도구를 사용해 GraphQL service에 request를 만들 때는 query와 variable을 하나의 JSON object 안의 두 field로 전달한다:

$ 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는 필요할 때 query에 포함할 수 있는 재사용 가능한 단위이다. 자세한 내용은 공식 GraphQL documentation를 참조한다. 다음 예시는 Move value를 나타내는 재사용 가능한 snippet을 factor out하기 위해 fragment를 사용한다:

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은 여러 종류의 잠재적으로 nested된 데이터를 가져오는 query를 지원한다. 예를 들어 다음 query는 epoch 97의 처음 10개 transaction과 함께 digest, sender address, transaction 비용 지불 후 반환된 gas object, gas price, gas budget을 가져온다:

query {
epoch(epochId: 97) {
transactions(first: 10) {
pageInfo {
hasNextPage
endCursor
}
nodes {
digest
sender {
address
}
effects {
gasEffects {
gasObject {
address
}
}
}
gasInput {
gasPrice
gasBudget
}
}
}
}
}

하나의 응답에 반환하기에는 transaction이 너무 많다면 service는 transactionBlock query 같은 variable size response에 대해 최대 page size limit을 적용하고, 추가 결과는 pagination을 통해 가져와야 한다.

Connections

paginated response를 반환하는 field는 다음 optional parameter를 받는다:

  • first: 끝에서 초과 결과를 버리는 방식으로 충족되는 page size 제한.
  • after: 결과를 아래쪽에서 배타적으로 제한하는 cursor.
  • last: 시작에서 초과 결과를 버리는 방식으로 충족되는 page size 제한.
  • before: 결과를 위쪽에서 배타적으로 제한하는 cursor.

이 field는 또한 GraphQL Cursor Connections Specification을 따르는 type을 반환하는데, 이는 이름이 Connection으로 끝나며 최소한 다음 field를 포함한다는 뜻이다:

  • PageInfo type의 pageInfo. 이는 반환된 페이지의 앞이나 뒤에 더 많은 page가 있는지를 나타낸다.
  • nodes: paginated response의 내용을 pagination 대상 type 목록으로 담는다(앞선 예시에서는 TransactionBlock).
  • edges: nodes와 비슷하지만 각 node를 해당 cursor와 연결한다.

Cursors

cursor는 paginated 결과를 위한 불투명한 식별자이다. cursor parameter(after, before 같은)의 유효한 source는 이전 paginated response의 cursor field(PageInfo.startCursor, PageInfo.endCursor, 또는 Edge.cursor 같은)뿐이다. cursor의 내부 format은 구현 세부사항이며 GraphQL service version 간에 고정되어 유지된다고 보장되지 않으므로 이에 의존해서는 안 된다. 임의로 cursor를 생성하는 것은 예상되지도 지원되지도 않는다.

cursor는 결과를 아래쪽에서(after) 또는 위쪽에서(before) 제한하는 데 사용된다. 두 경우 모두 제한은 배타적이므로 cursor가 가리키는 결과 자체는 제한된 영역에 포함되지 않는다.

Consistency

live object를 paginate하는 query의 cursor는 consistent pagination도 보장한다. 이 cursor는 query가 처음 실행된 checkpoint를 encode하므로, 이후 page는 새 checkpoint가 있어도 같은 checkpoint로 scoped된다. after cursor와 before cursor를 둘 다 제공한다면 둘 다 같은 checkpoint에서 온 것이어야 하며, 그렇지 않으면 query가 error를 발생시킨다.

기본적으로 RPC는 consistent pagination에 대해 대략 1시간의 retention을 제공한다.

Page limits

cursor를 사용해 결과를 제한한 뒤에는 firstlast parameter를 사용해 page size limit를 적용한다. service는 이 parameter가 최대 page size limit 이하일 것을 요구하며, 둘 다 제공하지 않으면 기본값을 선택한다. 제한을 설정하는 것 외에도 firstlast는 초과 요소를 어디서 버릴지 제어한다. 예를 들어 cursor 제한 적용 후 가능한 결과가 10개(R0, R1, …, R9) 있다면:

  • first: 3 제한은 R0, R1, R2를 선택한다.
  • last: 3 제한은 R7, R8, R9를 선택한다.
정보

firstlast 제한을 둘 다 적용하는 것은 error이다.

Scope

GraphQL request는 보고 있는 checkpoint를 제어하는 scope 안에서 평가된다. GraphQL service는 query에 응답할 때 이것이 마지막으로 실행된 checkpoint인 것처럼 동작한다. 기본적으로 이는 service가 모든 데이터를 가진 최신 checkpoint로 설정된다. partial response가 반환되는 것을 피하기 위해 service는 이보다 늦은 checkpoint를 query가 지정하는 것을 허용하지 않지만, 과거 query를 수행하기 위해 더 이른 checkpoint로 설정할 수는 있다.

선택적으로 scope는 dynamic field를 가져오는 query에만 적용되는 root object bound를 제공한다. query는 dynamic field를 특정 checkpoint 끝에서 존재하던 상태로 가져오거나, 해당 root object가 특정 version에 도달했을 때 존재하던 상태로 가져온다. wrapped object 또는 child(object-owned) object의 경우 root object는 다음과 같이 재귀적으로 정의된다:

  • wrapped되어 있다면, 그것이 wrapped된 object의 root object
  • 다른 object에 owned되어 있다면, 그 owner의 root object
  • object 자신

dynamic field의 root object version이 v라면, 그 자체 version ww <= v를 만족하는 최신 version이며, 이는 root object가 version v였을 때 존재하던 dynamic field의 최신 version을 뜻한다.

root object bound가 제공되지 않으면 dynamic field는 보고 있는 checkpoint에서 가져오며, checkpoint 기반 root object bound가 존재하더라도 보고 있는 checkpoint 자체에는 영향을 주지 않는다.

마지막으로 GraphQL service는 실행된 Mutation.executeTransaction과 simulation된 Query.simulateTransaction transaction 아래에 nested된 query를, 해당 transaction이 실행 또는 simulation된 직후이지만 그 transaction이 아직 index되지 않은 특별한 scope 안에 있는 것으로 취급한다.

query가 평가되는 scope는 어떤 field를 사용할 수 있는지에 영향을 준다. 특히 다음과 같다:

  • live object set query는 executed transaction scope 아래나 root object binding이 특정 version을 지정하는 경우에는 사용할 수 없다. 이러한 query는 checkpoint 수준에서 index된 데이터에 의존한다.
  • history를 paginate하는 query는 executed transaction scope 아래에서는 사용할 수 없다. indexing이 일어나기 전에는 system이 transaction이 history의 어디에 위치하는지 판단할 수 없다.

Setting checkpoint scope

Checkpoint.query를 사용해 과거 checkpoint에 대해 query를 실행할 수 있다. consistent live object set query(address의 owned object나 balance, 또는 object의 dynamic field를 가져오는 query 같은)의 경우 그 checkpoint에서 이전 query가 반환한 cursor를 사용해 계속 pagination할 수 있다.

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는 sequence number가 $cp인 checkpoint의 끝 시점 기준으로 실행될 마지막 5개의 transaction을 반환하고, NextBalancesPage는 cursor $after에서 끝난 page 다음의 $address용 다음 10개 balance를 가져온다. 두 접근 방식을 결합하여 live object query의 첫 page를 특정 checkpoint에서 가져오도록 보장할 수도 있다:

query FirstBalancesPageAtCheckpoint($address: SuiAddress!, $cp: UInt53) {
checkpoint(sequenceNumber: $cp) {
query {
address(address: $address) {
balances(first: 10) {
pageInfo {
hasNextPage
endCursor
}
nodes {
objectId
balance
}
}
}
}
}
}

이 query의 응답은 retention의 적용을 받는다. $cpQuery.transactions의 retention window 밖에 있으면 AtCheckpoint는 결과를 반환하지 않으며, consistent range 밖 checkpoint에서 NextBalancesPage를 계속 paginate하려는 시도는 error를 반환한다.

Setting root version scope

특정 version의 object를 가져오는 query 아래에 nested된 query는 그 version의 root object bound에 의해 scoped된다. 예를 들어 다음 query에서는 이름이 42u64인 dynamic field를, 소유 object가 version $v였을 때 존재하던 상태로 가져온다:

query ObjectsDynamicFields($id: SuiAddress!, $v: UInt53!) {
object(address: $id, version: $v) {
dynamicField(name: { literal: "42u64" }) {
value {
... on MoveValue {
json
}
}
}
}
}

이 속성은 nested dynamic field query에 재귀적으로 적용된다. 또한 root object를 atCheckpoint parameter를 사용해 특정 checkpoint에서 가져오거나 최신 checkpoint에서(모든 parameter를 생략하여) 가져오는 경우에도 적용된다. 이 경우 root object bound는 checkpoint 기반이다.

rootVersion parameter는 이 암시적 bound를 override한다. 이 parameter는 object를 해당 parameter가 지배하는 root version bound의 적용을 받는 것처럼 가져오며, 이는 그 아래에 nested된 query에도 적용된다. 이는 dynamic field를 직접(object로서) 가져올 때 필요한데, object가 root object가 아닌 한 child가 업데이트되어도 object의 version은 갱신되지 않기 때문이다.

다음 query에서 $id는 root object가 version $r였을 때 존재하던 상태로 가져온 dynamic field의 address이다. nested query는 dynamic field의 foo field에 저장된 wrapped object가 소유한 이름 42u64의 nested dynamic field를 가져온다. nested fetch는 같은 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
}
}
}
}
}
}
}

wrapped object에 대한 nested dynamic field query를 만들기 위해 Address를 반환하는 query를 사용할 수 있다. Address에는 연결된 version이 없지만, Query.address는 nested dynamic field query용 root object bound를 설정하기 위해 rootVersion 또는 atCheckpoint parameter를 받을 수 있다. 다음 query는 address가 $id인 object가 소유한(dynamic field의 owner가 wrapped object일 수도 있음) 이름 42u64의 dynamic field를, 그 root object가 version $r이었을 때 존재하던 상태로 가져온다:

query WrappedDynamicField($id: SuiAddress!, $r: UInt53!) {
address(address: $id, rootVersion: $r) {
dynamicField(name: { literal: "42u64" }) {
value {
... on MoveValue {
json
}
}
}
}
}

root object bound를 가진 scope 안에 nested되어 있는 동안에는 objectAt 또는 addressAt query를 사용해 그 bound를 재설정하거나 override할 수 있다. 이 field는 같은 entity를 질의하지만 history 안의 다른 위치에서 질의한다. 이 field에 아무 parameter도 제공하지 않으면 GraphQL service가 알고 있는 최신 checkpoint에서의 object 상태를 가져온다. 다음 query는 이전에 version $v로 가져온 object의 최신 version을 가져온다:

query LatestDynamicField($id: SuiAddress!, $v: UInt53!) {
object(address: $id, version: $v) {
objectAt {
version
}
}
}

Limits

Sui RPC용 GraphQL service는 network throughput을 최적화하고 과도하거나 남용적인 service 호출로부터 보호하기 위해 사용 가능한 모든 instance에서 rate-limit가 적용된다.

Rate limits

query는 분당 시도 횟수 기준으로 rate-limit되어 모든 사용자에게 service의 높은 가용성을 보장한다.

Query limits

rate limit 외에도 query는 node 수, query 깊이, payload 크기 같은 복잡성 규칙에 대해 검증된다. 이 limit를 가져오려면 serviceConfig field를 질의한다. 사용 가능한 limit 일부를 질의하는 예시는 다음과 같다:

{
serviceConfig {
maxQueryDepth
maxQueryNodes
maxOutputNodes
defaultPageSize(type: "Query", field: "transactions")
maxPageSize(type: "Query", field: "objects")
queryTimeoutMs
maxQueryPayloadSize
maxTypeArgumentDepth
maxTypeArgumentWidth
maxTypeNodes
maxMoveValueDepth
}
}

Rich queries

rich query는 backing store에 대한 전용 request를 요구한다. 하나의 GraphQL request 안에서 수행할 수 있는 rich query 수에는 limit가 있으며, 이 역시 serviceConfig에서 질의할 수 있다:

{
serviceConfig {
maxRichQueries
}
}

request가 허용된 limit보다 많은 rich query를 수행하면 초과된 rich query는 임의로 "RESOURCE_EXHAUSTED" error로 대체된다. rich query에는 다음이 포함된다:

  • IAddressable.objects, IAddressable.balances, IMoveObject.dynamicFields 같은 owned object query의 pagination.
  • Query.transactions, Query.events 같은 과거 query의 pagination.
  • Query.objectVersions, IObject.objectVersionsAfter, IObject.objectVersionsBefore 같은 package와 object version의 pagination.

Retention

서로 다른 query는 각자의 retention policy 적용을 받는다. vanilla한 general purpose setup에서는 live object set query는 최근 checkpoint(분 또는 시간 단위)에서만 동작하는 반면, transaction pagination은 적용된 filter에 따라 특정 checkpoint까지만 가능할 수 있다(주 또는 월 단위). 이 범위를 벗어난 데이터는 pruning된다.

Data source retention

GraphQL query는 retention 범위가 서로 다른 여러 data source에 의존한다:

Data sourceExamplesTypical retention
Consistent storeQuery.objects, Address.balance, objects by owner or type~1 hour
Database storeQuery.transactions, Query.events, Query.checkpoints~(30-90) days
아카이브 서비스Point lookups (transaction by digest, object by ID and version)Indefinite (if configured)
Operators

retention은 stack operator가 구성한 datasource pipeline의 pruning policy에 따라 달라진다. production 구성 예시는 GraphQL 및 General-purpose Indexer을 참조한다.

Querying available range

사용 가능한 checkpoint 범위는 serviceConfig.availableRange를 사용해 질의한다:

availableRange(type: String!, field: String, filters: [String!]): AvailableRange!
  • type: "Query" 또는 "Address" 같은 GraphQL type 이름.
  • field: "transactions" 또는 "events" 같은 그 type의 field.
  • filters: TransactionFilteraffectedAddress에 대해 [affectedAddress]처럼 filter input type의 field 이름, EventFiltermodule에 대해 [module]처럼 filter 이름, 또는 [version] 같은 직접 query parameter 이름.

query parameter를 filter 이름과 맞춘다: query가 filter: { affectedAddress: "0x..." }를 사용한다면 filters: ["affectedAddress"]를 전달한다.

Strictest retention is returned by the available range query.

Datasource pipeline은 pruning configuration에 따라 서로 다른 retention 범위로 구성될 수 있다. 여러 filter를 available range query에 전달하면, 해당 filter를 지원하는 pipeline 중 가장 엄격한 retention 범위가 반환된다.

Examples

# affected address로 filter한 transaction query의 available range를 확인한다
{
serviceConfig {
availableRange(type: "Query", field: "transactions", filters: ["affectedAddress"]) {
first {
sequenceNumber
}
last {
sequenceNumber
}
}
}
}
# affected object로 filter한 checkpoint transaction query의 available range를 확인한다
{
serviceConfig {
availableRange(type: "Checkpoint", field: "Transactions", filters: ["affectedObject"]) {
first {
sequenceNumber
}
last {
sequenceNumber
}
}
}
}
Nested queries

nested query의 각 field는 각자의 retention limit를 가진다:

query {
address(address: "0x...") {
# Consistent Store를 사용한다 (~1 hour retention)
dynamicFields(first: 10) {
nodes {
value {
... on MoveObject {
# DB Store를 사용한다 (retention이 다를 수 있다)
objectAt(checkpoint: 10579000) {
version
}
}
}
}
}
}
}

각 field의 retention을 확인하려면 serviceConfig.availableRange를 사용한다.

Handling "Outside available range" errors

데이터가 available range 밖에 있다는 error를 만나면, 이는 query가 pruning된 데이터를 요청하고 있다는 뜻이다. 이를 해결하려면:

  1. 긴 pagination 실행을 시작하기 전에 serviceConfig.availableRange를 사용해 먼저 available range를 확인한다.
  2. 새로운 cursor를 사용한다. 오래된 cursor는 이미 pruning된 checkpoint를 참조할 수 있다.
  3. query bound를 조정한다. afterCheckpoint/beforeCheckpoint filter가 available range 안에 있는지 확인한다.

Example queries

다음 query는 GraphQL로 수행할 수 있는 일반적인 작업을 보여준다.

Find the reference gas price for latest epoch

query {
epoch {
referenceGasPrice
}
}

Find a specific historical epoch

epoch 100의 총 stake reward, reference gas price, checkpoint 수, 총 gas fee를 찾는다. query에서 epochId argument는 optional이며 기본값은 latest epoch이다.

query {
epoch(epochId: 100)
{
epochId
totalStakeRewards
referenceGasPrice
totalCheckpoints
totalGasFees
totalStakeSubsidies
storageFund {
totalObjectStorageRebates
nonRefundableBalance
}
}
}

Find a transaction by its digest

digest로 transaction을 가져와 gas sponsor address, gas price, gas budget, 그 transaction 실행의 effect 같은 정보를 표시한다.

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

주어진 object를 건드린(수정, transfer, 삭제한) 모든 transaction을 찾는다. 이는 Coin, StakeSui, NFT 같은 object의 흐름을 추적하고 싶을 때 유용할 수 있다.

정보

이 예시는 GraphQL variablespagination을 사용한다.

query ($objectID: SuiAddress!) {
transactions(filter: {affectedObject: $objectID}) {
nodes {
sender {
address
}
digest
effects {
objectChanges {
nodes {
address
}
}
}
}
}
}

Variables

온라인 IDE를 사용할 때는 아래 JSON을 main editor 아래의 Variables window에 복사한다.

{
"objectID": "0x11c6ae8432156527fc2e12e05ac7db79f2e972510a823a4ef2e670f27ad7b52f"
}

Filter transactions by a function

public_transfer 함수를 Move call transaction command로 호출한 마지막 10개의 transaction을 찾는다.

정보

이 예시는 last filter를 사용한다. 이 경우 service가 알고 있는 마지막 10개 transaction만 반환한다.

{
transactions(
last: 10,
filter: {
function: "0x2::transfer::public_transfer"
}
) {
nodes { digest }
}
}

Find transaction balance changes

주어진 address가 staking 관련 함수를 호출한 모든 transaction의 balance change를 찾는다. 이는 staking 또는 unstaking 이력을 얻고 싶을 때 유용할 수 있다.

query ($address: SuiAddress!) {
transactions(filter: {
function: "0x3::sui_system::request_add_stake"
sentAddress: $address
}) {
nodes {
digest
effects {
balanceChanges {
nodes {
owner {
address
}
amount
}
}
}
}
}
}

Variables

온라인 IDE를 사용할 때는 아래 JSON을 main editor 아래의 Variables window에 복사한다.

{
"address": "0xa9ad44383140a07cc9ea62d185c12c4d9ef9c6a8fd2f47e16316229815862d23"
}

Fetch a dynamic field on an object

정보

이 예시는 alias와 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

object의 dynamic field를 paginate한다. 이는 table과 bag 같은 온체인 데이터 구조의 element를 순회하는 데 사용할 수 있다. Move에서 사용 가능한 dynamic collection에 대해 더 알아보려면 The Move Book을 참조한다.

정보

이 예시는 fragmentsvariables를 사용한다.

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

genesis checkpoint에서 시작해 sequence number가 증가하는 방향으로 한 번에 checkpoint 5개씩 읽는 paginated query를 설정한다. pageInfo.hasNextPage 값은 읽을 다음 page가 있는지를 결정한다. pageInfo.endCursor 값은 $after를 읽기 위한 cursor로 사용된다.

정보

이 예시는 GraphQL variablespagination을 사용한다.

query ($after: String) {
checkpoints(first: 5, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
digest
timestamp
}
}
}

Paginate checkpoints backwards

가장 최근에 index된 checkpoint에서 시작해 sequence number가 감소하는 방향으로 한 번에 checkpoint 5개씩 읽는 paginated query를 설정한다. pageInfo.hasPreviousPage 값은 읽을 이전 page가 있는지를 결정한다. pageInfo.startCursor 값은 $before를 읽기 위한 cursor로 사용된다.

정보

이 예시는 GraphQL variablespagination을 사용한다.

query ($before: String) {
checkpoints(last: 5, before: $before) {
pageInfo {
hasPreviousPage
startCursor
}
nodes {
digest
timestamp
}
}
}

Execute a transaction

transaction 실행은 transactionDataBcssignatures라는 2개의 argument를 받는다. transactionDataBcsSui Client CLI client call 명령이 생성할 수 있는 serialized unsigned transaction data이다. Move 함수를 호출하기 위해 명령에 --serialize-unsigned-transaction flag를 전달한다. Sui Keytool CLI 명령 sui keytool signsignatures를 생성할 수 있다.

mutation ($tx: String!, $sigs: [String!]!) {
executeTransaction(transactionDataBcs: $tx, signatures: $sigs) {
errors
effects {
status
epoch {
startTimestamp
}
gasEffects {
gasSummary {
computationCost
}
}
}
}
}

Variables

온라인 IDE를 사용할 때는 아래 JSON을 main editor 아래의 Variables window에 복사한다.

{
"tx": "AAACACAZXApmrHgzTs3FGDyXWka+wmMCy2IwOdKLmTWHb5PnFQEASlCnLAw4qfzLF3unH9or5/L7YpOlReaSEWfoEwhTqpavSxAAAAAAACCUFUCOn8ljIxcG9O+CA1bzqjunqr4DLDSzSoNCkUvu2AEBAQEBAAEAALNQHmLi4jgC5MuwwmiMvZEeV5kuyh+waCS60voE7fpzAa3v/tOFuqDvQ+bjBpKTfjyL+6yIg+5eC3dKReVwghH/rksQAAAAAAAgxtZtKhXTr1zeFAo1JzEqVKn9J1H74ddbCJNVZGo2I1izUB5i4uI4AuTLsMJojL2RHleZLsofsGgkutL6BO36c+gDAAAAAAAAQEIPAAAAAAAA",
"sigs": [
"AB4ZihXxUMSs9Ju5Cstuuf/hvbTvvycuRk2TMuagLYNJgQuAeXmKyJF9DAXUtL8spIsHrDQgemn4NmojcNl8HQ3JFqhnaTC8gMX4fy/rGgqgL6CDcbikawUUjC4zlkflwg=="
]
}

Migrating to GraphQL from JSON-RPC

다음 섹션의 예시는 JSON-RPC 호출과 그에 상응하는 GraphQL 구조를 모두 보여주기 위해 탭으로 구성되어 있다. 사용 가능한 모든 GraphQL 기능의 포괄적인 목록은 Sui RPC용 GraphQL (베타)를 참조한다.

Example 1: Get total transactions

network의 총 transaction 수를 가져온다.

{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getTotalTransactionBlocks",
"params": []
}

Example 2: Get a specific transaction

digest로 transaction을 가져온다.

{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getTransactionBlock",
"params": [
"Hay2tj3GcDYcE3AMHrej5WDsHGPVAYsegcubixLUvXUF",
{
"showInput": true,
"showRawInput": false,
"showEffects": true,
"showEvents": true,
"showObjectChanges": false,
"showBalanceChanges": false
}
]
}

Example 3: Get coin objects owned by an address

address가 소유한 모든 Coin<0x2::sui::SUI> object를 반환한다.

query {
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getCoins",
"params": [
"0x5094652429957619e6efa79a404a6714d1126e63f551f4b6c7fb76440f8118c9", //owner
"0x2::sui::SUI", //coin type
"0xe5c651321915b06c81838c2e370109b554a448a78d3a56220f798398dde66eab", //cursor
3 //limit
]
}

GraphQL에는 JSON-RPC로 재현할 수 없는 기능도 있으며, 예를 들면 다음과 같다:

  • checkpoint { query { ... } }를 사용한 time travel query.

  • nested dynamic field look-up(그리고 그 contents와 함께 1개의 request에서 dynamic field를 paginate하는 기능).

  • owner kind와 type으로 live object를 가져오는 기능(예: 특정 type의 모든 shared object).

  • 방금 실행된 transaction에서 deserialized input object와 output object contents를 가져오는 기능.

다음 예시는 JSON-RPC에서 사용할 수 없는 함수 일부를 보여준다.

Example 4: Getting objects by type

현재 온체인에서 live한 0x2::package::Publisher type object의 최신 version을 가져온다.

query {
objects(filter: { type: "0x2::package::Publisher" }) {
nodes {
address
digest
asMoveObject {
contents { json }
}
}
}
}

Example 5: Paging through package versions

Sui framework의 모든 version을 찾고 그 module을 나열한다:

query {
packageVersions(address: "0x2") {
nodes {
version
modules {
nodes {
name
}
}
}
}
}