# GraphQL Guide ###### tags: `FuelJourney` GraphQL is a powerful tool for frontend developers in building efficient and performant UI experiences. Fuel Labs has a GraphQL API that lets you interact with the data on the Fuel Network. This step-by-step GraphQL guide will help you get up-to-speed with GraphQL and learn how to use the Fuel GraphQL endpoint. #### Key Take-aways: - [What is GraphQL & Why you should use it]() - [Introduction to Fuel GraphQL API]() - [Implementing Network Explorer functionality in your dapp]() - [Advanced Concepts]() - [GraphQL Best Practices]() ## Overview Before you begin, let's go over some fundamentals! ### What is GraphQL? GraphQL is a query language for your APIs and a specification that describes the data in your API and how you can communicate with it. Using GraphQL, your frontend clients can request exactly data that they require from the API. GraphQL is a database agnostic API standard and can be paired with any frontend language. ### Why you should use GraphQL - Multiple resources in a single query - Schema Introspection & GraphiQL - Predictable query responses - Get exactly the data you asked for - Strong type system - Inherently Self-documenting #### Key Concepts: - **Queries**: GraphQL queries allow you to read data from your GraphQL server. If you want to get information from the network such as transactions, contract addresses, & more, you can write queries to request that data. Example: ```graphql= query Block{ id header transactions ``` The above query gets the id, header, and transactions of a given block. - **Mutatations**: GraphQL mutations allow you to write or update data in the server. If you want to update the chain's state, you can use mutations. Example: ```graphql= mutation ProduceBlock { produceBlocks(blocksToProduce: "", time: {blockTimeInterval: "", startTime: ""}) } ``` The above mutation lets you produces blocks, that can be used for testing that requires block advancement. - **Subscriptions**: GraphQL subscriptions allow you to request realtime data. For instance, you can write a subscription to poll the Fuel blockchain for transaction status and it will return a live stream of data. Example: ```graphql= subscription StatusChange { statusChange(id: "") { ... on SubmittedStatus { __typename time } } } ``` The above subscription returns a stream of status updates for the given transaction id if the current status is [TransactionStatus::Submitted]. > ❗️ Only supported in the latest beta-2 testnet. ### The Fuel GraphQL API Fuel Labs has created an open GraphQL API endpoint for the Fuel Network that allows you to interact with data on the Fuel blockchain. The **Fuel GraphQL API** lets you write complex queries to polpulate your frontend with a wide range of on-chain data such as transactions, balances, block information, and more. You can also use it to simulate and submit transactions on the Fuel network. ### Playground The GraphQL playground is an intuitive and interactive and graphical IDE that includes an editor for queries, mutations, and subscriptions. It also comes with a schema and documentation explorer to infer the underlying GraphQL schema and type system. It also provides query validation and context for the underlying GraphQL schema. You can tinker with the Fuel GraphQL API on the Playground to explore and work with the API: - [Beta-2 (latest testnet)](https://node-beta-2.fuel.network/playground) - [Beta-1 (first testnet)](https://node-beta-1.fuel.network/playground) ## Getting Started Great! 🎉 Now that you know what GraphQL is, let's connect the Fuel GraphQL API to your dapp and query the Fuel blockchain from your React frontend. #### Prerequisites This guides assumes that you have the fundamental knowledge of following concepts: - JavaScript or TypeScript - React To follow along, you will require the following tools installed on your machine: - npm - VS Code (alternatively, any other code editor of your choice) > 📝 Note: If you want to learn how to set up your frontend and write a smart contract in Sway, it recommended that you go through the following guides in the Fuel Journey before reading further: > > 1. [Sway Smart Contract]() > 2. [TS SDK Guide]() #### Installing dependencies 1. Installing Apollo-client ``` npm install @apollo/client graphql ``` #### Setting up Apollo Client ```react= import { ApolloClient, InMemoryCache, gql } from '@apollo/client' const apolloClient= new ApolloClient({ uri: 'https://node-beta-2.fuel.network/graphql', cache: new InMemoryCache(), }) const HEALTH_QUERY = ` query { health } ` export const checkHealth = async () => { const response = await apolloClient.query({ query: gql(HEALTH_QUERY), }); console.log("RESPONSE:", response); } ``` ## Querying from your dapp In this section, you will learn how to implement the following functionalities in your dapp: - Search for a given transaction/address - Display a list of 5 latest blocks - Display a list of latest transactions - Paginate the list of latest transactions as 5 per page Let's start building your frontend for the above functionality! ### Writing Queries In order to implement the above functionality, will be writing 3 main queries: 1. `HomePageSearchQuery` 2. `HomePageTransactionQuery` 3. `HomePageBlocksQuery` Let's start writing out queries in the `operations.graphql` file! 1. **Search for a given transaction or address** Your query should look something like this: ```graphql= query HomePageSearchQuery($transaction: TransactionId!, $address: Address!) { transaction(id: $transaction) { id } transactionsByOwner(owner: $address, first: 1) { edges { node { id } } } } ``` 2. **List the latest blocks** Your query should look as follows: ```graphql= query HomePageBlocksQuery($count: Int) { blocks(last: $count) { edges { cursor node { ...HomePageBlock } } } } fragment HomePageBlock on Block { id height time producer transactions { id } } ``` 3. **List the latest transactions** Your query should look something like this: ```graphql= query HomePageTransactionsQuery( $last: Int $first: Int $before: String $after: String ) { transactions(first: $first, last: $last, before: $before, after: $after) { pageInfo { hasPreviousPage hasNextPage startCursor endCursor } edges { node { ...HomePageTransaction } } } } fragment HomePageTransaction on Transaction { id inputContracts { id } inputAssetIds gasPrice gasLimit maturity isScript receiptsRoot witnesses outputs { __typename ... on CoinOutput { to amount assetId } ... on ContractOutput { inputIndex balanceRoot stateRoot } ... on ChangeOutput { to amount assetId } ... on VariableOutput { to amount assetId } ... on ContractCreated { contract { id } } } inputs { __typename ... on InputCoin { owner } ... on InputContract { contract { id } } } status { ... on SubmittedStatus { time } ... on SuccessStatus { time } ... on FailureStatus { time } } } ``` ### Writing your frontend To implement the functionalities above, you need to write two pages: 1. **HomePage:** A page that serves as the landing page for your block explorer and displays the search field and latest blocks and transactions. 2. **TransactionPage:** A page that is displayed when a user searches for a transaction ID. ## Advanced Concepts #### GraphQL Fragments For complex operations, GraphQL offers reusable logic called Fragments that lets you define a set of fields that can be further shared between queries or mutations that have repeating fields. For instance, to get the ```graphql= fragment BlockPage on Block { id header { height time applicationHash } transactions { __typename } } query Block($height: U64, $previousHeight: U64) { block(height: $height) { ...BlockPage } previousBlock: block(height: $previousHeight) { ...BlockPage } } ``` #### Inline Fragments Fragments in GraphQL can also be defined as follows (as previously defined in queries): ```graphql= query LatestTransactions { transactions(last: 5) { outputs { __typename ... on CoinOutput { to amount assetId } ... on ContractOutput { inputIndex balanceRoot stateRoot } } } } ``` In the above query, `... on` is used to define inline fragments to specify the query fields for the return types `CoinOutput` & `ContractOutput` for the union `Output`. #### Advanced SDL The Fuel GraphQL API offers the following advanced language features: - **Scalars:** Types that define concrete data such as `AssetId`, `BlockId`, `ContractId`, etc. Example: ```graphql= query contractBalance{ contract assetId } ``` In the above query, `assetId` is a 32 byte unique ID used to identify a coin. On the testnet, the assetId is `0x0000000000000000000000000000000000000000000000000000000000000000`. - **Enums:** Types that define other resources that contain a set of values. For instance,`CoinStatus` describes status of a UTXO:`spent` or `unspent`. ```graphql= enum CoinStatus { UNSPENT SPENT } ``` - **Unions:** Types that define that a property should be one of a set of values. For instance, the union type `Input` expresses that a transaction could either be a `coin`, a `contract`, or a `message`. See the following types of `Input` and their corresponding meaning in the query below that you have written in the above sections: 1. `InputCoin`: Input type for a coin 2. `InputContract`: Input type for a contract 3. `InputMessage`: Input type for a message ```graphql= query LatestTransactions { transactions(last: 5) { nodes { id inputs { __typename ... on InputCoin { owner utxoId amount assetId } ... on InputContract { utxoId contract { id } } ... on InputMessage { messageId sender recipient amount data } } ``` ## GraphQL Best Practices ### Pagination The Fuel GraphQL API offers queries that return information that can be paginated, such as transactions. Let's take a look at how pagination is facilitated with the endpoint in Fuel. `Connections:` Connections are a type of response used whenever you are expecting multiple results that may require pagination. Each query return type that ends in "Connection" will include the following return fields: ```graphql= pageInfo: PageInfo! edges: [SomethingEdge!]! nodes: [Something!]! ``` - **PageInfo** `pageInfo`: returns an object that includes information about the returned page of results: `hasPreviousPage`: Boolean! Whether or not the result has a previous page. `hasNextPage: Boolean!` Whether or not the result has another page after it. `startCursor: String` The starting cursor that identifies the first page. `endCursor: String` The end cursor that identifies the last page. - **Edges** `edges` returns an array of edge objects, which includes the cursor and first node for that page. You can use this data to help with pagination. - **Nodes** `nodes` returns an array of whichever type you are expecting paginated results for. ### Caching APIs allow clients to cache query responses to avoid re-fetching of data in cases where the same resources are being queried multiple times. GraphQL caching can be facilitated by defining unique identifiers to allow clients like Apollo client to cache queries responses. Apollo Client particularly stores query responses in a local storage called `InMemorycache` in the form of a table. ### Authorization Authorization is business logic that lets you grant access to certain functionality or data from your API, only to certain users. For instance, you only want the owner of a wallet to be able to check the wallet balance or asset info. This can be achieved through authorization. Best practice is to implement the permissions logic in your business logic instead of directly inside your GraphQL resolver code. ## Additional Resources - [Official GraphQL Website](https://graphql.org/) - [Fuel GraphQL API Docs](https://graphql-docs.fuel.network/) - [Learn more about GraphQL](https://graphql.org/learn/) - [How To GraphQL](https://www.howtographql.com/)