Nine Chronicles GraphQL API Guide

💡
This document demonstrates the features of the core API released in March 2021. Nine Chronicles is a serverless game, so there is no central API server, but you can use the GraphQL interface locally by running the client. Currently, NCG (Nine Chronicles Gold) transfer is only available through API, so those who have done NCG transactions will be familiar with it.

What's Nine Chronicles?

Nine Chronicles is an online game without servers — like Bitcoin or BitTorrent, the gamers and miners connect to each other to power a distributed game network.
We believe decentralized infrastructure has created new possibilities for online gaming. Just like blockchain ecosystems, communities will be able to powerfully decentralized games that are widely open for creative experimentation. Since these community-powered worlds are open source and perpetual, talented game designers and developers can take over a stagnant world any time and breathe a new life into it. For more information, visit docs.nine-chronicles.com.

Getting started

You must first launch the game launcher to begin — if you haven't gotten started, please visit nine-chronicles.com to join our early access.
After launching the game, open the internet browser and access http://localhost:23061/ui/playground to load the GraphQL playground. In addition to the official client, headless builds can be used. When developing new services, try the steps below with the headless build, which is easier to execute on a server machine like Linux environment.

Accessing agent and shop data from the playground

Let's search the store information through the playground and buy the desired item. Key information in the game can be inquired through querystateQuery. First, we will obtain the player's avatar address to facilitate the inquiry. This can be queried with an agent query, and then details can be viewed through an avatar query.
The agent's address can be copied from the launcher's login screen or from the bottom right.
query { stateQuery { agent(address: "0xA116d45d176aeD204a7627A470e87907e57BE6CD") { avatarAddresses } avatar(address:"0x122a60B6a56CC0D23Aad4A07c9E724d49044eB6D") { actionPoint level agentAddress } } }
GraphQL
{ "data": { "stateQuery": { "agent": { "avatarAddresses": [ "0x122a60B6a56CC0D23Aad4A07c9E724d49044eB6D" ] }, "avatar": { "actionPoint": 100, "level": 158, "agentAddress": "0xA116d45d176aeD204a7627A470e87907e57BE6CD" } } }, "extensions": {} }
JSON
In the game, there is a difference between the properties managed by the agent and the properties managed by the avatar. For example, gold is managed by the agent, and equipment is managed by the avatar. Since product purchasing is a transaction between avatars, we will need to use our avatar address for this action.
Ok, then let's get the store information. If you use the playground's SCHEMA tab, you can check the information of the data that can be imported, and the auto-complete function is also provided so you can conveniently check your query. In this demo, let's search for foods less than 100 Gold.
query { stateQuery { shop { products(itemSubType: FOOD, maximumPrice: 100) { itemUsable { id itemId } price sellerAgentAddress sellerAvatarAddress productId } } } }
GraphQL
{ "data": { "stateQuery": { "shop": { "products": [ { "itemUsable": { "id": 201005, "itemId": "d19ca62e-3504-4ca7-83db-f0041ff47706" }, "price": "20 NCG", "sellerAgentAddress": "0x2609F8e941caB431F68Ec2772D963F5006341C7c", "sellerAvatarAddress": "0x16741aa2387ad785d45D154293B7dC98C3A8e084", "productId": "13e1de91-9271-40bb-86b7-c53140b62838" }, { "itemUsable": { "id": 201011, "itemId": "40fb0509-7f63-4815-a51d-3a976ea17ded" }, "price": "28 NCG", "sellerAgentAddress": "0x3a3aDe342Dd061cCb1B7b4a011d7648fb509e441", "sellerAvatarAddress": "0xB781D43C5258e480f202EAEd4811ee05f680F797", "productId": "5e699ecb-5055-4233-a229-0d309a74e387" } ] } } }, "extensions": {} }
JSON

Create a buy action and check if the transaction id has been incorporated

By using GraphQL API, you can make transactions by executing mutations. For example, let's buy an item by entering the required information in the buy query. Before executing, you need to log in to the game.
mutation { action { buy( buyerAvatarAddress:"0x122a60B6a56CC0D23Aad4A07c9E724d49044eB6D", sellerAgentAddress: "0x2609F8e941caB431F68Ec2772D963F5006341C7c", sellerAvatarAddress: "0x16741aa2387ad785d45D154293B7dC98C3A8e084", productId: "13e1de91-9271-40bb-86b7-c53140b62838") } }
GraphQL
After the execution is finished, you can see below that a transaction id is returned at the actionbuy key as follows. All actions are not immediately executed, but a transaction is created and propagated to the network in this way, and the actual execution is completed when the transaction is incorporated into a block and connected to the chain. Therefore, you need to check the transfer status by looking up the transaction id. You must enter your own address as an argument.
{ "data": { "action": { "buy": "de5b3897f12b0d3f0387fc9572ea35c648a740106e2ac31e0bd138646417f2da" } }, "extensions": {} }
JSON
Transaction ids that have not yet been added to the block can be checked in stagedTxIds. It will be removed when the incorporation into the block is confirmed, so if the stageTxIds list becomes empty, it can be assumed that the corresponding transaction has entered the block.
query { nodeStatus { stagedTxIds(address: "0xA116d45d176aeD204a7627A470e87907e57BE6CD") } }
GraphQL
{ "data": { "nodeStatus": { "stagedTxIds": [ "de5b3897f12b0d3f0387fc9572ea35c648a740106e2ac31e0bd138646417f2da" ] } }, "extensions": {} }
JSON

Action completion and checking status

Did you check that the transaction id is missing from stagedTxIds? If so, it's time to check whether the purchase of the item was actually successful. Check if the item was successfully purchased by searching goldBalance and inventory as follows.
query { goldBalance(address: "0xA116d45d176aeD204a7627A470e87907e57BE6CD") stateQuery { avatar(address: "0x122a60B6a56CC0D23Aad4A07c9E724d49044eB6D") { inventory { consumables { id itemId } } } } }
GraphQL
{ "data": { "goldBalance": "890019.2", "stateQuery": { "avatar": { "inventory": { "consumables": [ { "id": 201005, "itemId": "d19ca62e-3504-4ca7-83db-f0041ff47706" } ] } } } }, "extensions": {} }
JSON

Check the game client

We have confirmed that the item has been successfully purchased through GraphQL! Can you check the game as well? When you run the game, you can also see that the purchase was successful.

Extension program development

There are various things that can be made using Nine Chronicles GraphQL API. In this document, we demonstrated an example using the playground, but you can create useful tools by calling GraphQL from other programs. Here is a simple web service for a store by copying the cURL from the shop request earlier.
GraphQL API can literally retrieve all the data from Nine Chronicles and perform any action. In addition, APIs will be provided for all functions to be added in the future. There will be cases where simple APIs such as transferGold will be shared first, but you can develop many additional functions on top of what the current core development team is working on.

Curious for More?

We have more repositories over on our Github, such as the block explorer and a sample Libplanet clicker project.
We're always happy to discuss your creative ideas for developing the Nine Chronicles ecosystem. Do check out our grant program, and hop onto our Discord to share your thoughts. Thanks!
Please join us at Planetarium Discord to share your ideas and feedback