Skip to content

Introduction

The ledger-subquery is a SubQuery-based indexer for the Fetch ledger. This indexer provides a Graphql API for querying tracked entities. For a list of tracked entities, see the schema.graphql file.

To learn more about how to run or change this SubQuery Project to get your own custom GraphQL API for your app, visit the SubQuery Academy for documentation.

Endpoints / Playground UIs

The graphql API endpoints also serve a playground UI to browsers for convenience. This UI is useful for rapid experimentation and iteration of queries as well as just getting some results, features include:

  • real-time query results
  • query editor:
  • auto-complete & validation via schema introspection
  • can store multiple, named queries
  • supports graphql variables
  • local persistence of query editor contents
  • schema reference
  • graphql docs reference
Network API / Playground URL
Fetchhub (mainnet) https://subquery.fetch.ai
Dorado (testnet) https://subquery-dorado.fetch.ai

Architecture

Component Diagram

subquery architecture component diagram legend subquery architecture component diagram

Querying

The graphql API relies heavily on postgraphile (as a library) to resolve graphql requests.

Postgraphile plugins also play a critical role; in particular, the connection-filter and pg-aggregates plugins.

Pagination

The graphql API implements the connections specification for pagination (see: GraphQL pagination docs for more).

!!! tip It is recommended to prefer using pagination operators by default (e.g. first: <limit>) to avoid unnecessary delays in query responses.

Filtering

Filtering is facilitated by postgraphile and its plugins. For specifics on supported operators and how to use them, please refer to their documentation:

Examples

Filtering NativeTransfers for a given sender address:

query nativeTransfersFromAddress {
  nativeTransfers(first: 5, filter: {
    fromAddress: {
      equalTo: "fetch1t3qet68dr0qkmrjtq89lrx837qa2t05265qy6s"
    }
  }) {
    nodes {
      toAddress
      amounts
    }
  }
}

Filtering for Messages from a given sender address:

query messagesFromAddress {
  messages (first: 5, filter:  {
    transaction: {
      signerAddress: {
        equalTo: "fetch1t3qet68dr0qkmrjtq89lrx837qa2t05265qy6s"
      }
    }
  }) {
    nodes {
      transaction {
        signerAddress
      }
    }
  }
}

Filtering on Eventss within a given timeframe and with a given type:

query transferEventsDuring {
  events(first: 5, filter:  {
    block: {
      timestamp: {
        greaterThanOrEqualTo: "2022-09-15T01:44:13.719",
        lessThanOrEqualTo: "2022-09-19T02:15:28.632"
      }
    },
    type: {equalTo: "transfer"},
  }) {
    nodes {
      attributes
    }
  }
}

Aggregation

Aggregation is facilitated by the pg-aggregates plugin. Features include:

  • calculating aggregates
  • grouped aggregates
  • applying conditions to grouped aggregates
  • ordering by relational aggregates
  • filtering by the results of aggregates on related connections

Tests as examples

Additional examples of queries and use cases can be found in the end-to-end test suite.

Entities

Entities tracked by the indexer exist at varying levels of abstraction. "Lower-level" entities include the primitives (i.e. blocks, transactions, messages, and events), upon which "higher-level" entities are constructed (e.g. LegacyBridgeSwaps).

Some entities are derived from objects which do not correspond to any network state change (e.g. failed transactions and their messages). In the case of failed transactions, it is desirable to index the associated data for end-user reference. This notion may also apply to other objects but should be considered carefully to avoid storing invalid or useless data.

Primitive entities

(see: schema.graphql)

  • blocks
  • transactions
  • messages
  • events

Relationship diagram

entity relationship diagram legend

entity relationship diagram