Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetching Data from Indexers and Integrating it to a frontend interface #736

Closed
wants to merge 5 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 240 additions & 0 deletions docs/smart-contracts/guides/dapps/indexers.mdx
Myestery marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
---
title: Fetching Data from Indexers and Integrating it to a frontend interface
---

### What are Indexers?
Myestery marked this conversation as resolved.
Show resolved Hide resolved

Indexers in the Stellar ecosystem are specialized services that continuously process and organize blockchain data, making it easily accessible and queryable. They play a crucial role in data management and retrieval by providing a more efficient way to access information compared to directly querying the blockchain.

### Role of Indexers

- **Data Organization**: Indexers structure blockchain data into easily searchable formats.
- **Quick Retrieval**: They allow for fast and efficient querying of historical data.
- **Reduced Load**: By using indexers, applications can reduce the load on the Stellar network.

### Types of Data Provided by Indexers

Stellar indexers can provide various types of data, including:

- Account balances and history
- Transaction details
- Operation logs
- Trade history
- Asset information
- Ledger entries
- Events from contracts

## 2. Setting up Data Retrieval

### Connecting with an Indexer

1. **Choose an Indexer**: Select a reliable Stellar indexer. Some popular options include:
- **[Mercury](https://mercurydata.app/)**
- **[SubQuery](https://subquery.network/)**

A bigger list of supported indexers can be found in the [tools](/docs/tools/developer-tools#data-indexers) section
Myestery marked this conversation as resolved.
Show resolved Hide resolved

2. **API Documentation**: Familiarize yourself with the chosen indexer's API documentation.

3. **Authentication**: Some indexers may require API keys. Obtain necessary credentials if required.

4. **Setup HTTP/GraphQL Client**: Use a library like Axios, Fetch API, or Apollo Client to make HTTP requests to the indexer.

### Step-by-Step Instructions for Querying Data

We are going to use the [Mercury](https://mercurydata.app/) indexer for this example to index a smart contract ([Events](https://github.com/stellar/soroban-examples/tree/main/events)) deployed at the address [CC6MWZMG2JPQEENRL7XVICAY5RNMHJ2OORMUHXKRDID6MNGXSSOJZLLF](https://stellar.expert/explorer/testnet/contract/CC6MWZMG2JPQEENRL7XVICAY5RNMHJ2OORMUHXKRDID6MNGXSSOJZLLF) on the soroban testnet.

The goal is to query the `'increment'` event emitted by the contract and display them in a frontend interface.

1. **Setup Account**:

- Sign up for an account on Mercury: https://test.mercurydata.app/signup
- Create a new project and add your contract address to the subscriptions: https://docs.mercurydata.app/video-tutorials/index-and-query-contract-events
- Collect API key from the project settings

2. **GraphQL Playground**:

- Open the GraphQL playground: https://api.mercurydata.app:2083/graphiql
- Use the following query to fetch the event data:

```graphql
query MyQuery {
eventByTopic(t2: "AAAADwAAAAlpbmNyZW1lbnQAAAA=") {
nodes {
contractId
topic1
topic2
data
txInfoByTx {
ledgerByLedger {
closeTime
sequence
}
memo
txHash
opCount
fee
}
}
}
}
```

```json
// fill the Headers with the API key
{
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiY2FyZC1pZ..."
}
```

## 3. Frontend Integration

### Install dependencies

1. **Install the GraphQL client and stellar client**:
```bash
npm install @apollo/client graphql @stellar/stellar-sdk
```

### Processing and Preparing Data

1. **Encode Event Names**: The event names need to be encoded to base64 xdr before querying the indexer. You can use the following code snippet to encode the event names

```javascript
const { xdr, scValToNative } = require("@stellar/stellar-sdk");
const val = xdr.ScVal.scvSymbol("increment").toXDR("base64");
console.log(val);

// Output: AAAADwAAAAlpbmNyZW1lbnQAAAA=
```

2. **Create a Parse Function**: The data returned from the indexer is in XDR format. You can use the following function to parse the XDR data:
```js
function parseXdr(eventXdr) {
const parseddr = scValToNative(xdr.ScVal.fromXDR(eventXdr, "base64"));
return parseddr;
}
```
3. **Create a Connection Function**:

```js
import React from "react";
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
useQuery,
gql,
} from "@apollo/client";

// Create the Apollo Client
const client = new ApolloClient({
uri: "https://api.mercurydata.app:2083/graphql",
cache: new InMemoryCache(),
headers: {
Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cC...",
},
});
```

4. **Fetch Data**: Here's an example of fetching event data:

```javascript
// Define the query
const GET_EVENT_BY_TOPIC = gql`
query MyQuery {
eventByTopic(t2: "AAAADwAAAAlpbmNyZW1lbnQAAAA=") {
nodes {
contractId
topic1
topic2
topic3
topic4
txInfoByTx {
ledgerByLedger {
closeTime
sequence
}
memo
data
txHash
opCount
fee
}
}
}
}
`;

// Create a component to fetch the data
function EventDataFetcher({ setEventData }) {
const { loading, error, data } = useQuery(GET_EVENT_BY_TOPIC);

useEffect(() => {
if (loading) console.log("Loading data...");
if (error) console.error("Error fetching data:", error);
if (data) {
console.log("Fetched data:", data);
setEventData(
data.eventByTopic.nodes.map((node) => {
return {
currentCount: parseXdr(node.data).currentCount,
updateTime: new Date(
node.txInfoByTx.ledgerByLedger.closeTime * 1000,
).toLocaleString(),
};
}),
);
}
}, [loading, error, data, setEventData]);

return null;
}
```

5. **State Management**: Use a state management solution (e.g., Redux, MobX, or React Context) to store and manage the fetched data.

6. **Error Handling**: Implement proper error handling to manage API request failures or data inconsistencies.

### Displaying Data Effectively

1. **Component Structure**: Create reusable components for different data types.

```jsx
// Wrap your app with ApolloProvider
function App() {
const [eventData, setEventData] = useState([]);

return (
<ApolloProvider client={client}>
<div>
<h1>Stellar Events Data Fetcher</h1>
<EventDataFetcher setEventData={setEventData} />
{eventData ? (
<div>
<h2>Fetched Events:</h2>
{eventData.map((event, index) => (
<div key={index}>
<p>Current Count: {event.currentCount}</p>
<p>Update Time: {event.updateTime}</p>
</div>
))}
</div>
) : (
<p>No data fetched yet</p>
)}
</div>
</ApolloProvider>
);
}

export default App;
```

2. **Security Concerns**: Ensure that sensitive data like API keys are stored securely and not exposed in the frontend code. Using a backend or serverless function to fetch data from the indexer can help protect sensitive information.

3. **Optimization**: Implement pagination or lazy loading to manage large datasets efficiently.

### Demo

You can find a working demo of this frontend integration [here](https://stellar-indexed.web.app). and the complete code [here](https://github.com/Myestery/stellar-indexed)
Loading