Getting Started


Apibara Typescript SDK

The Typescript SDK enables developers to connect to DNA streams using Typescript.

The Typescript SDK is great to develop applications that:

  • use web3 libraries like ethers.js and starknet.js,
  • reuse code between frontend and backend,
  • leverage the vast ecosystem of Typescript packages.


The Typescript SDK is comprised of the following packages:


Starknet stream#

The following example shows how to connect to a DNA stream to consume Starknet data.

We start by installing the @apibara/protocol and @apibara/starknet packages:

npm add @apibara/protocol @apibara/starknet

Then we can create a DNA client. If you're using a DNA stream hosted by Apibara, you will need to specify an API token. You can create an API token for free on the Apibara website.

import { StreamClient } from '@apibara/protocol'
// Grab Apibara DNA token from environment, if any.
const AUTH_TOKEN = process.env.AUTH_TOKEN
const client = new StreamClient({
url: '',
token: AUTH_TOKEN,

We need to configure the client to start streaming data. To do that, we need to specify the following:

  • filter: a DNA filter that is used to decide what data to send for each block.
  • finality: block data finality. Can be finalized to receive blocks that have accepted on L1 and are extremely unlikely to be part of a chain reorganization, accepted for blocks accepted on L2, and pending for pending blocks.
  • batch size: finalized data is sent in batches to speedup the syncing process. This parameter controls the size of each batch.
  • cursor: the starting cursor.

In this example, we create a Starknet filter for all Transfer events of the ETH token. Together with events, we want to receive block headers and storage changes.

import { StarkNetCursor, Filter, FieldElement, v1alpha2 as starknet } from '@apibara/starknet'
const address = FieldElement.fromBigInt(
const transferKey = [
// Create stream filter. The client will only receive the specified data.
// - header: included only if any other filter matches (`weak: true`)
// - events: all transfer events from the eth contract
// - state update: all storage diffs from the eth contract
const filter = Filter.create()
.withHeader({ weak: true })
.addEvent((ev) => ev.withFromAddress(address).withKeys(transferKey))
.withStateUpdate((su) => su.addStorageDiff((st) => st.withContractAddress(address)))

Finally, we send the filter together with the rest of the configuration to the server and start streaming block data. The server to client stream is an async iterator that handles low-level details such as reconnecting after disconnect.

const cursor = StarkNetCursor.createWithBlockNumber(1045)
batchSize: 10,
finality: v1alpha2.DataFinality.DATA_STATUS_ACCEPTED,
for await (const message of client) {
if ( {
for (let item of {
const block = starknet.Block.decode(item)
// use data in block

Edit on GitHub