Skip to content

Latest commit

 

History

History
83 lines (57 loc) · 5.5 KB

indexer.md

File metadata and controls

83 lines (57 loc) · 5.5 KB

Indexer lookups / searching

Indexer lookups / searching is a higher-order use case capability provided by AlgoKit Utils that builds on top of the core capabilities. It provides type-safe indexer API wrappers (no more Record<string, any> pain), including automatic pagination control.

To see some usage examples check out the automated tests.

To import the indexer functions you can:

import { indexer } from '@algorandfoundation/algokit-utils'

All of the indexer functions require you to pass in an indexer SDK client, which you can get from AlgorandClient via algorand.client.indexer. These calls are not made more easy to call by exposing via AlgorandClient and thus not requiring the indexer SDK client to be passed in. This is because we want to add a tiny bit of friction to using indexer, given it's an expensive API to run for node providers, the data from it can sometimes be slow and stale, and there are alternatives that allow individual projects to index subsets of chain data specific to them as a preferred option. In saying that, it's a very useful API for doing ad hoc data retrieval, writing automated tests, and many other uses.

Indexer wrapper functions

There is a subset of indexer API calls that are exposed as easy to use methods with correct typing exposed and automatic pagination for multi item returns.

Search transactions example

To use the indexer.searchTransaction method, you can follow this example as a starting point:

const transactions = await indexer.searchTransactions(algorand.client.indexer, (s) =>
  s.txType('pay').addressRole('sender').address(myAddress),
)

Automatic pagination example

To use the indexer.executePaginatedRequest method, you can follow this example as a starting point:

const transactions = await executePaginatedRequest(
  (response: TransactionSearchResults) => {
    return response.transactions
  },
  (nextToken) => {
    let s = algorand.client.indexer.searchForTransactions().txType('pay').address(myAddress).limit(1000)
    if (nextToken) {
      s = s.nextToken(nextToken)
    }
    return s
  },
)

It takes the first lambda to translate the raw response into the array that should keep getting appended as the pagination is followed and the second lambda constructs the request (without the .do() call), including populating the pagination token.

Indexer API response types

The response model type definitions for the majority of indexer API are exposed from the types/indexer namespace in AlgoKit Utils. This is so that you can have a much better experience than the default response type of Record<string, any> from the indexer client in algosdk. If there is a type you want to use that is missing feel free to submit a pull request to add the type(s).

To access these types you can import them:

import { /* ... */ } '@algorandfoundation/algokit-utils/types/indexer'

As a general convention, the response types are named {TypeName}Result for a single item result and {TypeName}Results for a multiple item result where {TypeName} is:

  • {Entity}Lookup for an API call response that returns a lookup for a single entity e.g. AssetLookupResult
  • {Entity}Search for an API call response that searches for a type of entity e.g. TransactionSearchResults
  • The UpperCamelCase name of a given model type as specified in the official documentation for any sub-types within a response e.g. ApplicationResult

The reason Result/Results is suffixed to the type is to avoid type name clashes for commonly used types from algosdk like Transaction.

To use these types with an indexer call you simply need to find the right result type and cast the response from .do() for the call in question, e.g.:

import { TransactionLookupResult } from '@algorandfoundation/algokit-utils/types/indexer'

...

const transaction = (await algorand.client.indexer.lookupTransactionByID(transactionId).do()) as TransactionLookupResult