Getting Started

Overview

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.

Packages#

The Typescript SDK is comprised of the following packages:

Examples#

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: 'mainnet.starknet.a5a.ch',
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(
'0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7'
)
const transferKey = [
FieldElement.fromBigInt(hash.getSelectorFromName('Transfer'))
]
// 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)))
.encode()

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)
client.configure({
filter,
batchSize: 10,
finality: v1alpha2.DataFinality.DATA_STATUS_ACCEPTED,
cursor,
})
for await (const message of client) {
if (message.data?.data) {
for (let item of message.data.data) {
const block = starknet.Block.decode(item)
// use data in block
}
}
}

Edit on GitHub