diff --git a/docs/bos/tutorial/indexer-tutorials/feed-indexer.md b/docs/bos/tutorial/indexer-tutorials/feed-indexer.md index 4a265658dca..43093203e63 100644 --- a/docs/bos/tutorial/indexer-tutorials/feed-indexer.md +++ b/docs/bos/tutorial/indexer-tutorials/feed-indexer.md @@ -595,3 +595,90 @@ async function _handlePostUnlike(postId, likeAuthorAccountId) { ``` Here we also search for an existing relevant post in the `posts` table and if one has been found, the `accountsLiked` is defined as to update it removing the account ID of the account that has performed the like action. Then a graphQL `delete` query is called to remove the like from the `post_likes` table. + +## Querying data from the indexer + +The final step is querying the indexer using the public GraphQL API. This can be done by writing a GraphQL query using the GraphiQL tab in the code editor. + +For example, here's a query that fetches `likes` from the _Feed Indexer_, ordered by `block_height`: + +```graphql +query MyQuery { + _near_feed_indexer_post_likes(order_by: {block_height: desc}) { + account_id + block_height + post_id + } +} +``` + +Once you have defined your query, you can use the GraphiQL Code Exporter to auto-generate a JavaScript or BOS Widget code snippet. The exporter will create a helper method `fetchGraphQL` which will allow you to fetch data from the indexer's GraphQL API. It takes three parameters: + +- `operationsDoc`: A string containing the queries you would like to execute. +- `operationName`: The specific query you want to run. +- `variables`: Any variables to pass in that your query supports, such as `offset` and `limit` for pagination. + +Next, you can call the `fetchGraphQL` function with the appropriate parameters and process the results. + +Here's the complete code snippet for a BOS component using the _Feed Indexer_: + +```js +const QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql/`; + +State.init({ +data: [] +}); + +const query = `query MyFeedQuery { + _near_feed_indexer_post_likes(order_by: {block_height: desc}) { + account_id + block_height + post_id + } + }` + +function fetchGraphQL(operationsDoc, operationName, variables) { + return asyncFetch( + QUERYAPI_ENDPOINT, + { + method: "POST", + headers: { "x-hasura-role": `_near` }, + body: JSON.stringify({ + query: operationsDoc, + variables: variables, + operationName: operationName, + }), + } + ); + } + +fetchGraphQL(query, "MyFeedQuery", {}).then((result) => { + if (result.status === 200) { + if (result.body.data) { + const data = result.body.data._near_feed_indexer_post_likes; + State.update({ data }) + console.log(data); + } + } +}); + +const renderData = (a) => { + return ( +
+ {JSON.stringify(a)} +
+ ); +}; + +const renderedData = state.data.map(renderData); +return ( + {renderedData} +); +``` + + +:::tip + +To view a more complex example, see this widget which fetches posts with proper pagination: [Posts Widget powered By QueryAPI](https://near.org/edit/roshaan.near/widget/query-api-feed-infinite). + +::: diff --git a/docs/bos/tutorial/indexer-tutorials/hype-indexer.md b/docs/bos/tutorial/indexer-tutorials/hype-indexer.md index e8a2cf85fa7..9cd8e62a7dc 100644 --- a/docs/bos/tutorial/indexer-tutorials/hype-indexer.md +++ b/docs/bos/tutorial/indexer-tutorials/hype-indexer.md @@ -70,14 +70,14 @@ The `comments` table has columns: - `receipt_id`: the receipt ID of the transaction that created the comment - `content`: the content of the comment -## Defining the Indexing Logic +## Defining the indexing logic The next step is to define the indexing logic. This is done by editing the `indexingLogic.js` file in the code editor. The logic for this indexer can be divided into two parts: 1. Filtering blockchain transactions for a specific type of transaction 2. Saving the data from the filtered transactions to the database -### Filtering Blockchain Transactions +### Filtering Blockchain transactions The first part of the logic is to filter blockchain transactions for a specific type of transaction. This is done by using the `getBlock` function. This function takes in a block and a context and returns a promise. The block is a Near Protocol block, and the context is a set of helper methods to retrieve and commit state. The `getBlock` function is called for every block on the blockchain. @@ -130,7 +130,7 @@ async function getBlock(block: Block, context) { Again, like with the [`posts-indexer`](./posts-indexer.md) or the [`feed-indexer`](./feed-indexer.md), this filter selects transactions that are of type `FunctionCall` to the `set` method on the contract `social.near` on the network. In addition, it searches for `post` or `index` string in the data for the call. -### Saving the Data to the Database +### Saving the data to the Database The second part of the logic is to save the data from the filtered transactions to the database. This section also performs the filtering of transactions for posts and comments that contain "PEPE" or "DOGE" in the contents. @@ -278,3 +278,100 @@ The logic for this looks like: } } ``` + +## Querying data from the indexer + +The final step is querying the indexer using the public GraphQL API. This can be done by writing a GraphQL query using the GraphiQL tab in the code editor. + +For example, here's a query that fetches `posts` and `comments` from the _Hype Indexer_, ordered by `block_height`: + +```graphql +query MyQuery { + _near_hype_indexer_posts(order_by: {block_height: desc}) { + account_id + block_height + content + } + _near_hype_indexer_comments(order_by: {block_height: desc}) { + account_id + block_height + content + } +} +``` + +Once you have defined your query, you can use the GraphiQL Code Exporter to auto-generate a JavaScript or BOS Widget code snippet. The exporter will create a helper method `fetchGraphQL` which will allow you to fetch data from the indexer's GraphQL API. It takes three parameters: + +- `operationsDoc`: A string containing the queries you would like to execute. +- `operationName`: The specific query you want to run. +- `variables`: Any variables to pass in that your query supports, such as `offset` and `limit` for pagination. + +Next, you can call the `fetchGraphQL` function with the appropriate parameters and process the results. + +Here's the complete code snippet for a BOS component using the _Hype Indexer_: + +```js +const QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql/`; + +State.init({ +data: [] +}); + +const query = `query MyHypeQuery { + _near_hype_indexer_posts(order_by: {block_height: desc}) { + account_id + block_height + content + } + _near_hype_indexer_comments(order_by: {block_height: desc}) { + account_id + block_height + content + } + }` + +function fetchGraphQL(operationsDoc, operationName, variables) { + return asyncFetch( + QUERYAPI_ENDPOINT, + { + method: "POST", + headers: { "x-hasura-role": `_near` }, + body: JSON.stringify({ + query: operationsDoc, + variables: variables, + operationName: operationName, + }), + } + ); + } + +fetchGraphQL(query, "MyHypeQuery", {}).then((result) => { + if (result.status === 200) { + if (result.body.data) { + const data = result.body.data._near_hype_indexer_posts; + State.update({ data }) + console.log(data); + } + } +}); + +const renderData = (a) => { + return ( +
+ {JSON.stringify(a)} +
+ ); +}; + +const renderedData = state.data.map(renderData); +return ( + {renderedData} +); +``` + + +:::tip + +To view a more complex example, see this widget which fetches posts with proper pagination: [Posts Widget powered By QueryAPI](https://near.org/edit/roshaan.near/widget/query-api-feed-infinite). + +::: diff --git a/docs/bos/tutorial/indexer-tutorials/posts-indexer.md b/docs/bos/tutorial/indexer-tutorials/posts-indexer.md index 6923778e9a3..1106266e603 100644 --- a/docs/bos/tutorial/indexer-tutorials/posts-indexer.md +++ b/docs/bos/tutorial/indexer-tutorials/posts-indexer.md @@ -160,3 +160,90 @@ The `context.graphql` function for this indexer looks like this: ); } ``` + +## Querying data from the indexer + +The final step is querying the indexer using the public GraphQL API. This can be done by writing a GraphQL query using the GraphiQL tab in the code editor. + +For example, here's a query that fetches `posts` from the _Posts Indexer_, ordered by `block_height`: + +```graphql +query MyQuery { + _near_posts_indexer_posts(order_by: {block_height: desc}) { + content + block_height + account_id + } +} +``` + +Once you have defined your query, you can use the GraphiQL Code Exporter to auto-generate a JavaScript or BOS Widget code snippet. The exporter will create a helper method `fetchGraphQL` which will allow you to fetch data from the indexer's GraphQL API. It takes three parameters: + +- `operationsDoc`: A string containing the queries you would like to execute. +- `operationName`: The specific query you want to run. +- `variables`: Any variables to pass in that your query supports, such as `offset` and `limit` for pagination. + +Next, you can call the `fetchGraphQL` function with the appropriate parameters and process the results. + +Here's the complete code snippet for a BOS component using the _Posts Indexer_: + +```js +const QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql/`; + +State.init({ +data: [] +}); + +const query = `query MyPostsQuery { + _near_posts_indexer_posts(order_by: {block_height: desc}) { + content + block_height + account_id + } + }` + +function fetchGraphQL(operationsDoc, operationName, variables) { + return asyncFetch( + QUERYAPI_ENDPOINT, + { + method: "POST", + headers: { "x-hasura-role": `_near` }, + body: JSON.stringify({ + query: operationsDoc, + variables: variables, + operationName: operationName, + }), + } + ); + } + +fetchGraphQL(query, "MyPostsQuery", {}).then((result) => { + if (result.status === 200) { + if (result.body.data) { + const data = result.body.data._near_posts_indexer_posts; + State.update({ data }) + console.log(data); + } + } +}); + +const renderData = (a) => { + return ( +
+ {JSON.stringify(a)} +
+ ); +}; + +const renderedData = state.data.map(renderData); +return ( + {renderedData} +); +``` + + +:::tip + +To view a more complex example, see this widget which fetches posts with proper pagination: [Posts Widget powered By QueryAPI](https://near.org/edit/roshaan.near/widget/query-api-feed-infinite). + +::: diff --git a/website/sidebars.json b/website/sidebars.json index 4af392e0dc3..7832d2de4b2 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -561,13 +561,27 @@ ] }, { - "Community Components": ["bos/community/indexers"] + "BOS API": [ + "bos/api/home", + "bos/api/cache", + "bos/api/clipboard", + "bos/api/fetch", + "bos/api/near", + "bos/api/primitives", + "bos/api/social", + "bos/api/state", + "bos/api/storage" + ] }, { - "BOS API": ["bos/api/home", "bos/api/cache", "bos/api/clipboard", "bos/api/fetch", "bos/api/near", "bos/api/primitives", "bos/api/social", "bos/api/state", "bos/api/storage"] + "Dev Tools": [ + "bos/dev/intro", + "bos/dev/vscode", + "bos/dev/bos-loader" + ] }, { - "Dev Tools": ["bos/dev/intro", "bos/dev/vscode", "bos/dev/bos-loader"] + "Indexing Tools": ["bos/community/indexers"] }, { "type": "html", @@ -618,7 +632,12 @@ "value": " NEAR Social " }, { - "Social DB": ["social/intro", "social/contract", "social/standards", "social/tech"] + "Social DB": [ + "social/intro", + "social/contract", + "social/standards", + "social/tech" + ] } ], "integrate": [ diff --git a/website/static/docs/assets/QAPIScreen.png b/website/static/docs/assets/QAPIScreen.png index dc0daccfb71..6ec7823f1ee 100644 Binary files a/website/static/docs/assets/QAPIScreen.png and b/website/static/docs/assets/QAPIScreen.png differ diff --git a/website/static/docs/assets/QAPIScreen2.png b/website/static/docs/assets/QAPIScreen2.png index 85c61777525..7442a9470be 100644 Binary files a/website/static/docs/assets/QAPIScreen2.png and b/website/static/docs/assets/QAPIScreen2.png differ