Apibara Python SDK

API Reference

apibara.starknet

This module provides helpers to build StarkNet data filters and to decode StarkNet block data.

Cursor#

The SDK provides an helper function to create StarkNet-specific cursors.

Cursors contains an "order key" and a "unique key". Order keys represent block numbers and are used to order blocks of data. Since, because of chain reorganizations, it's possible to have multiple blocks with the same number, cursors include a block's hash as unique key to uniquely identify a block.

from apibara.starknet.cursor import starknet_cursor
# simple cursor
cursor = starknet_cursor(18_000)
# cursor with block hash included
cursor = starknet_cursor(18_000, "0x0534...f04a")

FieldElement#

The Apibara stream encodes StarkNet field elements (also known as felts) into 4 uint64 numbers. The SDK provides helper functions to convert from this representation into Python's int or str.

from apibara.starknet import felt
# converts felt to hex
felt.to_hex(my_felt)
# converts felt to int
felt.to_int(my_felt)
# converts from hex to felt
felt.from_hex("0x0534...123f")
# converts from int to felt
felt.from_int(1234)

Filter#

Class to build data filters. You can find more about filters in the StarkNet section.

from apibara.starknet import Filter
filter = Filter().with_header()
class Filter:
def __init__(self):
...
def encode(self) -> bytes:
"""Encodes the filter to bytes."""
def with_header(self, weak: Optional[bool] = None) -> Filter:
"""
Include header in the returned data.
Set `weak = True` to include block headers only if any other
filter matches.
"""
def add_transaction(self, tx: TransactionFilter) -> Filter:
"""
Include transaction data.
Use an empty filter to return all transactions.
"""
def add_event(self, ev: EventFilter) -> Filter:
"""
Include event data.
Use an empty filter to include all events.
"""
def add_message(self, msg: MessageFilter) -> Filter:
"""
Include messages from L2 to L1.
Use an empty filter to include all messages.
"""
def with_state_update(self, state_update: StateUpdateFilter) -> Filter:
"""
Include state updates.
"""

TransactionFilter#

# This filter matches any transaction.
Filter().add_transaction(TransactionFilter.any())
# This filter matches all deploy transactions
Filter().add_transaction(TransactionFilter.deploy())
class TransactionFilter:
@classmethod
def any(cls) -> "TransactionFilter":
"""
Include any transaction.
"""
@classmethod
def invoke_v0(cls) -> "InvokeV0TransactionFilter":
"""
Include invoke transactions, v0.
"""
@classmethod
def invoke_v1(cls) -> "InvokeV1TransactionFilter":
"""
Include invoke transactions, v1.
"""
@classmethod
def deploy(cls) -> "DeployTransactionFilter":
"""
Include deploy transactions.
"""
@classmethod
def declare(cls) -> "DeclareTransactionFilter":
"""
Include declare transactions.
"""
@classmethod
def l1_handler(cls) -> "L1HandlerTransactionFilter":
"""
Include L1 handle transactions.
"""
@classmethod
def deploy_account(cls) -> "DeployAccountTransactionFilter":
"""
Include deploy account transactions.
"""
class InvokeV0TransactionFilter:
def with_contract_address(
self, address: FieldElement
) -> "InvokeV0TransactionFilter":
"""
Filter by contract address.
"""
def with_entry_point_selector(
self, selector: FieldElement
) -> "InvokeV0TransactionFilter":
"""
Filter by entry point selector.
"""
def with_calldata(
self, calldata: List[FieldElement]
) -> "InvokeV0TransactionFilter":
"""
Filter by calldata prefix.
"""
class InvokeV1TransactionFilter:
def with_sender_address(self, address: FieldElement) -> "InvokeV1TransactionFilter":
"""
Filter by sender address.
"""
def with_calldata(
self, calldata: List[FieldElement]
) -> "InvokeV1TransactionFilter":
"""
Filter by calldata prefix.
"""
class DeployTransactionFilter:
def with_contract_address_salt(
self, address: FieldElement
) -> "DeployTransactionFilter":
"""
Filter by contract address salt.
"""
def with_class_hash(self, class_hash: FieldElement) -> "DeployTransactionFilter":
"""
Filter by class hash.
"""
def with_constructor_calldata(
self, calldata: List[FieldElement]
) -> "DeployTransactionFilter":
"""
Filter by constructor calldata prefix.
"""
class DeclareTransactionFilter:
def with_sender_address(self, address: FieldElement) -> "DeclareTransactionFilter":
"""
Filter by sender address.
"""
def with_class_hash(self, class_hash: FieldElement) -> "DeclareTransactionFilter":
"""
Filter by class hash.
"""
class L1HandlerTransactionFilter:
def with_contract_address(
self, address: FieldElement
) -> "L1HandlerTransactionFilter":
"""
Filter by contract address.
"""
def with_entry_point_selector(
self, selector: FieldElement
) -> "L1HandlerTransactionFilter":
"""
Filter by entry point selector.
"""
def with_calldata(
self, calldata: List[FieldElement]
) -> "L1HandlerTransactionFilter":
"""
Filter by calldata prefix.
"""
class DeployAccountTransactionFilter:
def with_contract_address_salt(
self, address: FieldElement
) -> "DeployAccountTransactionFilter":
"""
Filter by contract address salt.
"""
def with_class_hash(
self, class_hash: FieldElement
) -> "DeployAccountTransactionFilter":
"""
Filter by class hash.
"""
def with_constructor_calldata(
self, calldata: List[FieldElement]
) -> "DeployAccountTransactionFilter":
"""
Filter by constructor calldata prefix.
"""

EventFilter#

This filter is used to filter events.

# This filter matches events emitted by `address`.
filter = Filter.add_event(
EventFilter().with_from_address(address)
)
class EventFilter:
def with_from_address(self, address: FieldElement) -> "EventFilter":
"""
Filter by address of the contract emitting the event.
"""
def with_keys(self, keys: List[FieldElement]) -> "EventFilter":
"""
Filter by keys prefix.
"""
def with_data(self, data: List[FieldElement]) -> "EventFilter":
"""
Filter by data prefix.
"""

MessageFilter#

This filter is used to filter messages from L2 to L1.

class MessageFilter:
def with_to_address(self, address: FieldElement) -> "MessageFilter":
"""
Filter by address.
"""
def with_payload(self, payload: List[FieldElement]) -> "MessageFilter":
"""
Filter by payload prefix.
"""

StateUpdateFilter#

This filter is used to include state update data.

class StateUpdateFilter:
def add_storage_diff(self, diff: "StorageDiffFilter") -> "StateUpdateFilter":
"""
Includes all storage changes that match the filter.
"""
def add_declared_contract(
self, decl: "DeclaredContractFilter"
) -> "StateUpdateFilter":
"""
Includes all declared contracts that match the filter.
"""
def add_deployed_contract(
self, deploy: "DeployedContractFilter"
) -> "StateUpdateFilter":
"""
Includes all deployed contracts that match the filter.
"""
def add_nonce_update(self, update: "NonceUpdateFilter") -> "StateUpdateFilter":
"""
Includes all nonce updates that match the filter.
"""
class StorageDiffFilter:
def with_contract_address(self, address: FieldElement) -> "StorageDiffFilter":
"""
Filter by contract address.
"""
class DeclaredContractFilter:
def with_class_hash(self, class_hash: FieldElement) -> "DeclaredContractFilter":
"""
Filter by class hash.
"""
class DeployedContractFilter:
def with_contract_address(self, address: FieldElement) -> "DeployedContractFilter":
"""
Filter by contract address.
"""
def with_class_hash(self, class_hash: FieldElement) -> "DeployedContractFilter":
"""
Filter by class hash.
"""
class NonceUpdateFilter:
def with_contract_address(self, address: FieldElement) -> "NonceUpdateFilter":
"""
Filter by contract address.
"""
def with_nonce(self, nonce: FieldElement) -> "NonceUpdateFilter":
"""
Filter by nonce.
"""

Block#

The Block class is automatically generated from the following protobuf definition.

// Apibara StarkNet Support
syntax = "proto3";
package apibara.starknet.v1alpha2;
import "google/protobuf/timestamp.proto";
import "v1alpha2/types.proto";
// A StarkNet block.
message Block {
// Block status.
BlockStatus status = 1;
// Block header.
BlockHeader header = 2;
// Transactions in the block.
repeated TransactionWithReceipt transactions = 3;
// State update caused by the block.
StateUpdate state_update = 4;
// Events emitted in the block.
repeated EventWithTransaction events = 5;
// Messages to L1 sent in the block.
repeated L2ToL1MessageWithTransaction l2_to_l1_messages = 6;
}
// Block header.
message BlockHeader {
// Hash of the block.
FieldElement block_hash = 1;
// Hash of the block's parent.
FieldElement parent_block_hash = 2;
// Block height.
uint64 block_number = 3;
// Sequencer address.
FieldElement sequencer_address = 4;
// New state root after the block.
FieldElement new_root = 5;
// Timestamp when block was produced.
google.protobuf.Timestamp timestamp = 6;
}
// Status of a block.
enum BlockStatus {
// Unknown block status.
BLOCK_STATUS_UNSPECIFIED = 0;
// Block not accepted yet.
BLOCK_STATUS_PENDING = 1;
// Block accepted on L2.
BLOCK_STATUS_ACCEPTED_ON_L2 = 2;
// Block finalized on L1.
BLOCK_STATUS_ACCEPTED_ON_L1 = 3;
// Block was rejected and is not part of the canonical chain anymore.
BLOCK_STATUS_REJECTED = 4;
}
// A transaction with its receipt.
message TransactionWithReceipt {
// The transaction
Transaction transaction = 1;
// The transaction receipt.
TransactionReceipt receipt = 2;
}
// A transaction.
message Transaction {
// Common transaction metadata.
TransactionMeta meta = 1;
oneof transaction {
// Transaction invoking a smart contract, V0.
InvokeTransactionV0 invoke_v0 = 2;
// Transaction invoking a smart contract, V1.
InvokeTransactionV1 invoke_v1 = 3;
// Transaction deploying a new smart contract.
DeployTransaction deploy = 4;
// Transaction declaring a smart contract.
DeclareTransaction declare = 5;
// Transaction handling a message from L1.
L1HandlerTransaction l1_handler = 6;
// Transaction deploying a new account.
DeployAccountTransaction deploy_account = 7;
}
}
// Common transaction metadata.
message TransactionMeta {
// Transaction hash.
FieldElement hash = 1;
// Maximum fee to be paid.
FieldElement max_fee = 2;
// Signature by the user.
repeated FieldElement signature = 3;
// Nonce.
FieldElement nonce = 4;
// Version.
uint64 version = 5;
}
// Transaction invoking a smart contract, V0.
message InvokeTransactionV0 {
// Target contract address.
FieldElement contract_address = 1;
// Selector of the function being invoked.
FieldElement entry_point_selector = 2;
// Raw calldata.
repeated FieldElement calldata = 3;
}
// Transaction invoking a smart contract, V1.
message InvokeTransactionV1 {
// Address sending the transaction.
FieldElement sender_address = 1;
// Raw calldata.
repeated FieldElement calldata = 2;
}
// Transaction deploying a new smart contract.
message DeployTransaction {
// Raw calldata passed to the constructor.
repeated FieldElement constructor_calldata = 2;
// Salt used when computing the contract's address.
FieldElement contract_address_salt = 3;
// Hash of the class being deployed.
FieldElement class_hash = 4;
}
// Transaction declaring a smart contract.
message DeclareTransaction {
// Class hash.
FieldElement class_hash = 1;
// Address of the account declaring the class.
FieldElement sender_address = 2;
}
// Transaction handling a message from L1.
message L1HandlerTransaction {
// Target contract address.
FieldElement contract_address = 2;
// Selector of the function being invoked.
FieldElement entry_point_selector = 3;
// Raw calldata.
repeated FieldElement calldata = 4;
}
// Transaction deploying a new account.
message DeployAccountTransaction {
// Raw calldata passed to the constructor.
repeated FieldElement constructor_calldata = 2;
// Salt used when computing the contract's address.
FieldElement contract_address_salt = 3;
// Hash of the class being deployed.
FieldElement class_hash = 4;
}
// Result of the execution of a transaction.
//
// This message only contains the receipt data, if you also need the
// transaction, request a `Transaction`.
message TransactionReceipt {
// Hash of the transaction.
FieldElement transaction_hash = 1;
// Transaction's indexe in the list of transactions in a block.
uint64 transaction_index = 2;
// Feed paid.
FieldElement actual_fee = 3;
// Messages sent to L1 in the transactions.
repeated L2ToL1Message l2_to_l1_messages = 4;
// Events emitted in the transaction.
repeated Event events = 5;
}
// Message sent from L2 to L1 together with its transaction and receipt.
message L2ToL1MessageWithTransaction {
// The transaction that sent this message.
Transaction transaction = 1;
// The transaction receipt.
TransactionReceipt receipt = 2;
// The message.
L2ToL1Message message = 3;
}
// Message sent from L2 to L1.
message L2ToL1Message {
// Destination address.
FieldElement to_address = 3;
// Data contained in the message.
repeated FieldElement payload = 4;
}
// Event emitted by a transaction, together with its transaction and receipt.
message EventWithTransaction {
// The transaction emitting the event.
Transaction transaction = 1;
// The transaction receipt.
TransactionReceipt receipt = 2;
// The event.
Event event = 3;
}
// Event emitted by a transaction.
message Event {
// Address of the smart contract emitting the event.
FieldElement from_address = 1;
// Event key.
repeated FieldElement keys = 2;
// Event data.
repeated FieldElement data = 3;
}
// State update.
message StateUpdate {
// New state root.
FieldElement new_root = 1;
// Previous state root.
FieldElement old_root = 2;
// State difference.
StateDiff state_diff = 3;
}
// Difference in state between blocks.
message StateDiff {
// Storage differences.
repeated StorageDiff storage_diffs = 1;
// Contracts declared.
repeated DeclaredContract declared_contracts = 2;
// Contracts deployed.
repeated DeployedContract deployed_contracts = 3;
// Nonces updated.
repeated NonceUpdate nonces = 4;
}
// Difference in storage values for a contract.
message StorageDiff {
// The contract address.
FieldElement contract_address = 1;
// Entries that changed.
repeated StorageEntry storage_entries = 2;
}
// Storage entry.
message StorageEntry {
// Storage location.
FieldElement key = 1;
// Storage value.
FieldElement value = 2;
}
// Contract declared.
message DeclaredContract {
// Class hash of the newly declared contract.
FieldElement class_hash = 1;
}
// Contract deployed.
message DeployedContract {
// Address of the newly deployed contract.
FieldElement contract_address = 1;
// Class hash of the deployed contract.
FieldElement class_hash = 2;
}
// Nonce update.
message NonceUpdate {
// Contract address.
FieldElement contract_address = 1;
// New nonce value.
FieldElement nonce = 2;
}