Tezos Foundation

    Get started



Even though the TezTok indexer supports a wide range of token and marketplace contracts by default, users tend to have additional requirements that are sometimes not covered by the indexer. If we would add every requested feature to the core, it would soon become unmaintainable. As a solution to this problem, the indexer has a plugin system that allows users to extend the core with additional functionality.
If you want to extend the indexer with a plugin, it means that you have to run an instance of the indexer on your own server and add the plugin there. Alternatively, you can ask/hire us for support on developing and hosting plugins. Here are some things that can be achieved with plugins:
  • Creation of new event types
  • Creation of new data models (e.g. user models, auction models, etc.)
  • Accumulation of statistics
  • Data processing (e.g. download and extract colors of artifacts)

Getting Started

Plugins are added to
as subfolders and then need to be loaded in
. If a plugin introduces new event handlers, their types need to be registered in
A plugin can create its own Postgres tables. This can be achieved by adding a typescript file with the name
into the folder of the plugin. This file needs to default export a function that creates the database tables. TezTok uses the knex library to create database tables. Take a look at
as an example of a
In order to create the tables, the indexer needs to be built first by running the
npm run build
command and then the tables can be created by running the command
node ./build/scripts/create-plugin-tables.js <plugin-name>


The plugin system provides several hooks that can be used by a plugin to extend the indexer's functionality. These are the available hooks:


Every time a new block gets created on the Tezos Blockchain, the indexer fetches that block and parses all transactions and originations, and then creates normalized TezTok events that get stored in the database. For example, there are mint events, sale events, transfer events, etc.
hook gets called after a block was parsed and a set of teztok events were created. Example:
import { onEventsProduced } from '../plugins'; onEventsProduced(async (events) => { console.log(`${events.length} events created.`); });


The way the TezTok indexer works is that it creates and stores an event history for each token (and potentially other entities, like collections, split contracts, etc.) and then uses these events to build data models. So for example, if one edition of a token gets transferred to a burn address, the indexer creates a `FA2_TRANSFER` event first and then adds a rebuild job for that token to a queue. A worker then executes the rebuild job and re-creates the data model of the token from the event history. In the case of the example, the token would have one edition less after the rebuild.
hook gets triggered every time such a token-related rebuild happens. Example:
import { onTokenRebuild } from '../plugins'; onTokenRebuild(async ({ token, listings, offers, holders }) => { console.log(`the token with the contract address ${token.fa2_address} and the id ${token.token_id} has been rebuild.`, token, listings, offers, holders); });


Similar to the token model, a plugin can introduce its own data models and rebuild them every time certain TezTok events occur. In order to rebuild the custom data models, the
hook can be used. Example:
onRebuild(async (type, payload) => { if (type !== 'my-custom-data-model') { return; } // rebuild data model });


The indexer has a separate queue that is responsible for fetching token metadata from IPFS. The
hook gets triggered every time metadata got fetched from IPFS. Example:
import { onMetadataFetched } from '../plugins'; onMetadataFetched(async (metadataUri, metadata) => { console.log(`fetched ${metadataUri} from ipfs.`, metadata); });

registerTransactionEventHandler, registerOriginationEventHandler

A plugin can introduce its own event types by registering transaction or origination event handlers.
import { registerTransactionEventHandler, registerOriginationEventHandler } from '../plugins'; import MyTransactionHandler from './handlers/my_transaction_handler'; import MyOriginationHandler from './handlers/my_origination_handler'; registerTransactionEventHandler(MyTransactionHandler); registerOriginationEventHandler(MyOriginationHandler);

Example Plugin

The TezTok indexer repository contains one example plugin called
) that extends the indexer with the ability to index teia users and teia split contracts. It's a good starting point to learn more about how plugins can be coded.