Skip to main content

Indexing the Orca DEX

In this step-by-step tutorial we will look into a squid that gets data about the Orca Exchange NFTs, their transfers and owners from the Solana blockchain. Pre-requisites: Node.js v20 or newer, Git, Docker.

Download the project

Begin by retrieving the template and installing the dependencies:

Interfacing with the Whirlpool program

First, we inspect the data available for indexing. In Solana, most programs use the Anchor framework. Anchor makes the metadata describing the shape of the instructions, transactions and contract variables available as an Interface Definition Language (IDL) JSON file. For many popular programs (including Whirlpool) IDL files are published on-chain. SQD provides a tool for retrieving program IDLs and generating boilerplate ABI code for data decoding. This can be done with
Here, src/abi is the destination folder and the whirlpool suffix sets the base name for the generated file. Checking out the generated src/abi/whirlpool/instructions.ts file. It exports an instruction instance for every instruction in the ABI. Here’s how it is initialized for swap:
Here, d8 are the eight bytes that the relevant instruction data starts with.

Configuring the data source

“Data source” is a component that defines what data should be retrieved and where to get it. To configure the data source to retrieve the data produced by the swap instruction of the Whirlpool program, we initialize it like this:
src/main.ts
Here,
  • the Portal URL selects the public Solana mainnet dataset;
  • 259_984_950 is a Solana slot number, which Portal uses as the block range coordinate;
  • the argument of addInstruction() selects swap instructions from the Whirlpool program by program ID and discriminator.
  • The argument of setFields() specifies the exact fields we need for every data item type.
See the Solana Portal stream reference for more options. With a data source it becomes possible to retrieve filtered blockchain data from SQD Network, transform it and save the result to a destination of choice.

Decoding the event data

The other part the squid processor (the ingester process of the indexer) is the callback function used to process batches of the filtered data, the batch handler. In Solana Squid SDK it is typically defined within a run() call, like this:
Here,
  • dataSource is the data source object described in the previous section
  • database is a Database implementation specific to the target data sink. We want to store the data in a PostgreSQL database and present with a GraphQL API, so we provide a TypeormDatabase object here.
  • ctx is a batch context object that exposes a batch of data (at ctx.blocks) and any data persistence facilities derived from db (at ctx.store). See Block data for Solana for details on how the data batches are presented.
Batch handler is where the raw on-chain data is decoded, transformed and persisted. This is the part we’ll be concerned with for the rest of the tutorial. We begin by defining a database and starting the data processing:
src/main.ts
This goes through all the instructions in the block, verifies that they indeed are swap instruction from the Whirlpool program and decodes the data of each inner instruction. Then it retrieves the transaction from the decoded inner instruction and source and destination accounts. The decoding is done with the tokenProgram.instructions.transfer.decode function from the Typescript ABI provided in the project. At this point the squid is ready for its first test run. Execute
You can verify that the data is being stored in the database by running
The full code can be found here.