### Cursor Usage Example Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Demonstrates how to create a cursor to start streaming from a specific block number or a finalized block. ```rust use apibara_dna_protocol::dna::stream::Cursor; // Start from block 1000 let cursor = Cursor::new_with_block_number(1000)?; // Start from a finalized block let finalized = Cursor::new_finalized(999); ``` -------------------------------- ### Full Example: Streaming Starknet USDC Transfers Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md This example demonstrates how to connect to the Apibara API, build a filter for specific Starknet events (USDC transfers), and stream the data. It includes connection setup, filter construction, and message processing with reorg handling. ```rust use apibara_sdk::{ StreamClientBuilder, StreamDataRequestBuilder, BearerTokenFromEnv, starknet::{FilterBuilder, EventFilterBuilder, FieldElement}, }; use apibara_dna_protocol::dna::stream::{stream_data_response, DataFinality}; use std::sync::Arc; use tokio_stream::StreamExt; #[tokio::main] async fn main() -> Result<()> { // Connect let mut client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(BearerTokenFromEnv::default())) .connect("https://api.apibara.com".parse()?) .await?; // USDC contract and Transfer event on Starknet let usdc = FieldElement::from_hex( "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f368a8" )?; let transfer = FieldElement::from_hex( "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" )?; // Build filter for all USDC transfers let filter = FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(usdc) .with_keys(true, vec![Some(transfer)]) .with_transaction() .build() ) .build(); // Build request let request = StreamDataRequestBuilder::new() .with_finality(DataFinality::Finalized) .add_filter(filter) .build(); // Stream and process let mut stream = client.stream_data(request).await?; let mut block_count = 0; while let Some(message) = stream.try_next().await? { match message { stream_data_response::Message::Data(data) => { block_count += 1; println!( "Block: {} (events: {})", data.end_cursor.order_key, data.data.iter().map(|d| d.len()).sum::() ); // Save cursor for resumption if block_count % 100 == 0 { println!("Processed {} blocks", block_count); } } stream_data_response::Message::Invalidate(reorg) => { println!("Reorg at block {}", reorg.cursor.order_key); } stream_data_response::Message::Finalize(finalize) => { println!("Finalized block {}", finalize.cursor.order_key); } _ => {} } } Ok(()) } ``` -------------------------------- ### Complete Starknet Stream Client Example Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md A comprehensive example demonstrating how to connect to the Starknet stream, build a filter for specific events, and stream data. ```rust use apibara_sdk::{ StreamClientBuilder, StreamDataRequestBuilder, BearerTokenFromEnv, starknet::{FilterBuilder, EventFilterBuilder, FieldElement}, }; use std::sync::Arc; #[tokio::main] async fn main() -> Result<()> { // Connect let mut client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(BearerTokenFromEnv::default())) .connect("https://api.apibara.com".parse()?) .await?; // Build filter let usdc = FieldElement::from_hex("0x053c912...")?; let transfer = FieldElement::from_hex("0x99cd8b...")?; let filter = FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(usdc) .with_keys(true, vec![Some(transfer)]) .with_transaction() .build() ) .build(); // Build request let request = StreamDataRequestBuilder::new() .add_filter(filter) .build(); // Stream data let mut stream = client.stream_data(request).await?; while let Some(message) = stream.try_next().await? { // Process message } Ok(()) } ``` -------------------------------- ### Full Configuration Example for StreamClientBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md This example demonstrates how to configure various options for the `StreamClientBuilder` before connecting, including bearer token providers, timeouts, message size limits, and custom metadata. ```rust use apibara_sdk::{ StreamClientBuilder, BearerTokenFromEnv, MetadataMap, }; use std::{sync::Arc, time::Duration}; let mut metadata = MetadataMap::new(); // Add custom metadata if needed let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(BearerTokenFromEnv::default())) .with_timeout(Duration::from_secs(120)) .with_max_message_size_bytes(50 * 1024 * 1024)) .with_metadata(metadata) .connect("https://api.apibara.com".parse()?) .await?; ``` -------------------------------- ### Complete Stream Data Request Example Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Illustrates creating a StreamDataRequest using a builder, setting finality, starting cursor, and filters, then streaming data. ```rust use apibara_sdk::StreamDataRequestBuilder; use apibara_dna_protocol::dna::stream::{Cursor, DataFinality}; // Start from a specific block let cursor = Cursor::new_with_block_number(12345)?; // Create request for specific block data let request = StreamDataRequestBuilder::new() .with_finality(DataFinality::Finalized) .with_starting_cursor(Some(cursor)) .add_filter(your_filter) .build(); // Stream data let mut stream = client.stream_data(request).await?; // Process messages while let Some(message) = stream.try_next().await? { // Handle message } ``` -------------------------------- ### DataFinality Example with Serialization Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Demonstrates creating a DataFinality instance and serializing it to JSON. This example shows how to use the enum and its JSON representation. ```rust use apibara_dna_protocol::dna::stream::DataFinality; let finality = DataFinality::Finalized; assert!(finality.is_finalized()); // JSON serialization let json = serde_json::to_string(&finality)?; assert_eq!(json, "\"finalized\""); ``` -------------------------------- ### Cursor Example with Serialization and Deserialization Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Demonstrates creating a Cursor, serializing it to JSON, and deserializing it back. This example highlights cursor management and data interchange. ```rust use apibara_dna_protocol::dna::stream::Cursor; use serde_json; // Create from block number let cursor = Cursor::new_with_block_number(1000)?; assert_eq!(cursor.order_key, 999); // Serialize to JSON let json = serde_json::to_string(&cursor)?; // Deserialize from JSON let restored: Cursor = serde_json::from_str(&json)?; assert_eq!(cursor, restored); ``` -------------------------------- ### Example Authorization Header Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md A concrete example of an Authorization header with a bearer token. ```text Authorization: Bearer sk_live_abc123def456 ``` -------------------------------- ### Create MetadataKey Instance Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Example of creating a MetadataKey instance from a static string. Ensure the key is ASCII. ```rust use apibara_sdk::MetadataKey; let key = MetadataKey::from_static("x-custom-header"); ``` -------------------------------- ### Custom BearerTokenProvider Implementation Example Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Example of implementing a custom BearerTokenProvider for complex authentication, such as fetching tokens from a vault. Ensure any async operations are handled during initialization. ```rust use apibara_sdk::BearerTokenProvider; struct VaultTokenProvider { vault_url: String, } impl BearerTokenProvider for VaultTokenProvider { fn get_token(&self) -> Result { // Note: you must do async work at initialization time let token = self.cached_token.clone(); Ok(token) } } // Usage let provider = VaultTokenProvider { vault_url: "https://vault.example.com".to_string() }; let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(provider)) .connect(url) .await?; ``` -------------------------------- ### StreamDataRequest Construction Example Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Shows how to construct a StreamDataRequest using `StreamDataRequestBuilder`. This is the recommended way to build requests with various options. ```rust use apibara_sdk::StreamDataRequestBuilder; let request = StreamDataRequestBuilder::new() .with_finality(DataFinality::Accepted) .with_starting_cursor(Some(cursor)) .add_filter(filter) .build(); ``` -------------------------------- ### Connect with Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Example of building a StreamClientBuilder and connecting to a URL with custom metadata. The metadata will be included in all subsequent requests. ```rust use apibara_sdk::StreamClientBuilder; let client = StreamClientBuilder::new() .with_metadata(metadata) .connect(url) .await?; ``` -------------------------------- ### Set Up Development Environment with Nix Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Enter the development environment with all necessary dependencies installed using Nix. This command ensures you have the correct Cargo, Rust version, and external tools. ```bash nix develop ``` -------------------------------- ### Construct and Insert into MetadataMap Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Example of creating a new MetadataMap and inserting key-value pairs. Values must be parsed into MetadataValue. ```rust use apibara_sdk::MetadataMap; let mut metadata = MetadataMap::new(); metadata.insert("x-api-version", "v1".parse()?); ``` -------------------------------- ### FieldElement Example Usage Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Demonstrates how to create a FieldElement from a hex string and convert it to bytes using the provided methods. ```rust use apibara_sdk::starknet::FieldElement; let address = FieldElement::from_hex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7")?; let bytes = address.to_bytes(); ``` -------------------------------- ### StreamClientBuilder::new() Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md Creates a new StreamClientBuilder with default configuration. This is the starting point for configuring a connection. ```APIDOC ## StreamClientBuilder::new() ### Description Create a new `StreamClientBuilder` with default configuration. ### Returns `StreamClientBuilder` — A new builder with default settings. ### Default Configuration: - No bearer token provider - Maximum message size: unlimited - Timeout: 60 seconds - TLS: native roots - Metadata: empty ### Example: ```rust let builder = StreamClientBuilder::new(); ``` ``` -------------------------------- ### Create MetadataValue Instance Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Example of creating a MetadataValue instance from a static string. Ensure the value is ASCII. ```rust use apibara_sdk::MetadataValue; let value = MetadataValue::from_static("my-value")?; ``` -------------------------------- ### ContractChangeFilterBuilder Examples Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Illustrates how to use the construction methods of ContractChangeFilterBuilder to filter for specific contract lifecycle events. ```rust // All contract changes ContractChangeFilterBuilder::all_changes() // Only class declarations ContractChangeFilterBuilder::declared_class() // Only deployments ContractChangeFilterBuilder::deployed_contract() ``` -------------------------------- ### Build StreamDataRequest with Starting Cursor Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Constructs a StreamDataRequest using the builder, specifying a starting cursor to resume streaming from a particular point. ```rust use apibara_sdk::StreamDataRequestBuilder; let request = StreamDataRequestBuilder::new() .with_starting_cursor(Some(cursor)) .build(); ``` -------------------------------- ### Builder Pattern Examples Source: https://github.com/apibara/dna/blob/main/_autodocs/API-surface.md Demonstrates common ways builders are used for configuration. Pattern 1 shows a type returning a builder, Pattern 2 shows creating a new builder, and Pattern 3 shows chaining methods to build a request. ```rust let builder = StreamClient::builder(); ``` ```rust let builder = StreamClientBuilder::new(); ``` ```rust let request = RequestBuilder::new() .with_option_1(value) .with_option_2(value) .build(); ``` -------------------------------- ### Set Starting Cursor for Stream Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Specifies a cursor to resume streaming from a specific block. Use None to start from the genesis block. ```rust use apibara_sdk::StreamDataRequestBuilder; use apibara_dna_protocol::dna::stream::Cursor; // Resume from block 12345 let cursor = Cursor::new_with_block_number(12346)?; let request = StreamDataRequestBuilder::new() .with_starting_cursor(Some(cursor)) .build(); ``` -------------------------------- ### Create New StreamClientBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md Creates a new StreamClientBuilder with default configuration settings. This is the starting point for configuring a client connection. ```rust pub fn new() -> Self ``` ```rust let builder = StreamClientBuilder::new(); ``` -------------------------------- ### Starknet Stream Data Request Example Source: https://github.com/apibara/dna/blob/main/_autodocs/chain-integrations.md Shows how to build a `StreamDataRequest` for Starknet data using `StreamClientBuilder` and `FilterBuilder`. It demonstrates adding an event filter for all contracts and events. ```rust use apibara_sdk::{ StreamClientBuilder, StreamDataRequestBuilder, starknet::{FilterBuilder, EventFilterBuilder}, }; let filter = FilterBuilder::new() .add_event(EventFilterBuilder::all_contracts_and_events().build()) .build(); let request = StreamDataRequestBuilder::new() .add_filter(filter) .build(); let mut stream = client.stream_data(request).await?; ``` -------------------------------- ### Inspect Metadata with Tonic Interceptor Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Advanced example showing how to create a custom Interceptor to log incoming request metadata. This is useful for debugging. ```rust use tonic::{service::Interceptor, Request}; struct LoggingInterceptor; impl Interceptor for LoggingInterceptor { fn call(&mut self, request: Request<()>) -> Result, tonic::Status> { for (key, value) in request.metadata().iter() { println!("Header: {} = {:?}", key, value); } Ok(request) } } ``` -------------------------------- ### Build a Starknet Filter Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Construct a Starknet filter using the fluent builder API. This example demonstrates adding an event filter for a specific contract and event key. ```rust use apibara_sdk::starknet::{FilterBuilder, EventFilterBuilder, FieldElement}; let filter = FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(usdc_address) .with_keys(true, vec![Some(transfer_key)]) .with_transaction() .build() ) .build(); ``` -------------------------------- ### Example gRPC Status Response Source: https://github.com/apibara/dna/blob/main/_autodocs/grpc-endpoints.md Illustrates the structure of a successful response from the status endpoint, showing cursor information for chain progress. ```json { "current_head": { "orderKey": 500000, "uniqueKey": "0xabcd..." }, "last_ingested": { "orderKey": 499990, "uniqueKey": "0xabcd..." }, "finalized": { "orderKey": 499500, "uniqueKey": "0xabcd..." }, "starting": { "orderKey": 0, "uniqueKey": "0x0000..." } } ``` -------------------------------- ### Add Transaction Filter Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Include a transaction filter in the main filter. This example adds a filter for all transaction types. ```rust FilterBuilder::new() .add_transaction( TransactionFilterBuilder::all_transaction_types() .build() ) ``` -------------------------------- ### StaticBearerToken Usage Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Example of using the StaticBearerToken provider with a hardcoded token string. This is suitable for static API keys or tokens. ```rust use apibara_sdk::StaticBearerToken; use std::sync::Arc; let token = "my-api-key-12345"; let provider = StaticBearerToken::new(token.to_string()); let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(provider)) .connect(url) .await?; ``` -------------------------------- ### Create a New FilterBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Initialize a new FilterBuilder to start composing Starknet filters. This creates a filter with the default header filter mode. ```rust let builder = FilterBuilder::new(); ``` -------------------------------- ### Starknet Event Data Structure Example Source: https://github.com/apibara/dna/blob/main/_autodocs/chain-integrations.md Illustrates the structure of protobuf-encoded block data for Starknet events, showing the `Data` message with cursor, finality, and encoded data fields. ```plaintext Data { cursor: Some(Cursor { order_key: 12345, unique_key: ... }), end_cursor: Cursor { order_key: 12345, unique_key: ... }, finality: FINALIZED, data: [ Vec, // Encoded starknet::Event for filter 0 Vec, // Encoded starknet::Event for filter 1 ], production: LIVE, } ``` -------------------------------- ### StreamData Request Flow Example Source: https://github.com/apibara/dna/blob/main/_autodocs/grpc-endpoints.md Illustrates a typical client-server interaction for the StreamData endpoint, including data, heartbeats, and reorg handling. ```plaintext Client sends StreamDataRequest with: - starting_cursor: block 12345 - finality: FINALIZED - filter: [starknet_event_filter] - heartbeat_interval: 30s Server responds with stream of StreamDataResponse: 1. Data(block 12346, 2 events) 2. Data(block 12347, 0 events, finalized) 3. Heartbeat() 4. Data(block 12348, 1 event) 5. Invalidate(reorg to 12347) // chain reorg 6. Data(block 12347, 1 event) // re-stream with new data ... ``` -------------------------------- ### Create New StreamDataRequestBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Initializes a new StreamDataRequestBuilder with default settings. The default finality is DataFinality::Accepted and it starts streaming from genesis. ```rust pub fn new() -> Self ``` -------------------------------- ### Rust gRPC Client Multiplexing Example Source: https://github.com/apibara/dna/blob/main/_autodocs/grpc-endpoints.md Demonstrates concurrent execution of gRPC calls (status and stream_data) on the same client instance using Tokio tasks. This leverages the underlying HTTP/2 multiplexing capabilities. ```rust let client_copy = client.clone(); let status_handle = tokio::spawn(async move { client_copy.status().await }); let stream_handle = tokio::spawn(async move { client.stream_data(request).await }); ``` -------------------------------- ### Handling StreamClientBuilderError Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md This example shows how to match on the `StreamClientBuilderError` enum to handle specific connection or authentication failures when calling the `connect` method. ```rust match builder.connect(url).await { Ok(client) => { /* use client */ }, Err(StreamClientBuilderError::Connection { source }) => { eprintln!("Failed to connect: {}", source); }, Err(StreamClientBuilderError::BearerToken { source }) => { eprintln!("Authentication failed: {}", source); }, } ``` -------------------------------- ### StreamDataRequestBuilder Options Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Details the configuration options for `StreamDataRequestBuilder`, allowing customization of data finality, starting cursor, and filters. ```APIDOC ## StreamDataRequestBuilder Options ### Description Details the configuration options for the `StreamDataRequestBuilder`, enabling fine-grained control over the data stream request. Users can specify the data maturity level, a starting point to resume a stream, and add filters to select specific data. ### Options Table | Method | Type | Default | Purpose | |--------|------|---------|---------| | `with_finality()` | `DataFinality` | Accepted | Data level | | `with_starting_cursor()` | `Option` | None | Resume position | | `add_filter()` | `impl Message` | — | Data selection | ``` -------------------------------- ### Common Headers for Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Examples of common headers that can be added to MetadataMap for API versioning, request tracking, client identification, and additional context. ```rust use apibara_sdk::MetadataMap; let mut metadata = MetadataMap::new(); // API versioning metadata.insert("x-api-version", "v1".parse()?); // Request tracking metadata.insert("x-trace-id", "my-trace-123".parse()?); // Client identification metadata.insert("x-client-name", "my-indexer".parse()?); // Additional context metadata.insert("x-environment", "production".parse()?); ``` -------------------------------- ### BearerTokenFromEnv Usage (Default Environment Variable) Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Example of using the default BearerTokenFromEnv provider with the StreamClientBuilder. Ensure the DNA_TOKEN environment variable is set. ```rust use apibara_sdk::BearerTokenFromEnv; use std::sync::Arc; // Uses DNA_TOKEN environment variable let provider = BearerTokenFromEnv::default(); let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(provider)) .connect(url) .await?; ``` -------------------------------- ### StreamClient::stream_data() Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client.md Starts streaming data from the server with optional heartbeat configuration. It returns a stream of data messages that can be processed asynchronously. ```APIDOC ## StreamClient::stream_data() ### Description Start streaming data from the server with optional heartbeat configuration. ### Method `async fn stream_data(&mut self, request: impl Into) -> Result` ### Parameters #### Request - **request** (`impl Into`) - Required - Request configuration, can be a `StreamDataRequest` or `StreamDataRequestBuilder` ### Returns `Result` — A stream of data messages that implements `tokio_stream::Stream`. ### Details - If the heartbeat interval is not already set, it defaults to half of the client timeout duration. - The heartbeat interval is communicated to the server to maintain the connection. - Messages are received through the returned stream using `StreamExt::try_next()`. ### Throws - `tonic::Status`: Connection error or server-side validation failure ### Example ```rust use apibara_sdk::StreamDataRequestBuilder; use tokio_stream::StreamExt; let request = StreamDataRequestBuilder::new() .with_starting_cursor(Some(cursor)) .build(); let mut stream = client.stream_data(request).await?; while let Some(message) = stream.try_next().await? { // Process message match &message { apibara_dna_protocol::dna::stream::stream_data_response::Message::Data(data) => { // Handle data block } apibara_dna_protocol::dna::stream::stream_data_response::Message::Heartbeat(_) => { // Connection is alive } apibara_dna_protocol::dna::stream::stream_data_response::Message::Invalidate(inv) => { // Handle reorganization } _ => {} } } ``` ``` -------------------------------- ### BearerTokenError Handling Example Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Demonstrates how to handle the different variants of BearerTokenError when calling get_token(). This allows for specific error messages based on the failure reason. ```rust match provider.get_token() { Ok(token) => { /* use token */ } Err(BearerTokenError::InvalidBearerTokenFormat { .. }) => { eprintln!("Token has invalid format"); } Err(BearerTokenError::External { message, .. }) => { eprintln!("Failed to get token: {}", message); } } ``` -------------------------------- ### Configure Header Filter Mode Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Set the header filter mode for the main filter. This example sets the header filter to 'Always' include block headers. ```rust FilterBuilder::new() .with_header(HeaderFilter::Always) ``` -------------------------------- ### BearerTokenFromEnv Usage (Custom Environment Variable) Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Example of configuring BearerTokenFromEnv to read from a custom environment variable. This allows flexibility in naming the token variable. ```rust use apibara_sdk::BearerTokenFromEnv; use std::sync::Arc; let provider = BearerTokenFromEnv::new_with_var_name( "MY_API_KEY".to_string() ); let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(provider)) .connect(url) .await?; ``` -------------------------------- ### Get DNA Server Status Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client.md Retrieve the current status of the DNA server, including head, ingested, finalized, and starting block cursors. ```rust let status = client.status().await?; let last_ingested = status.last_ingested.unwrap_or_default(); println!("Last ingested block: {}", last_ingested.order_key); ``` -------------------------------- ### Stream Data with Filters Source: https://github.com/apibara/dna/blob/main/sdk/README.md Builds a data stream request with specific filters for events from a contract and streams messages. Requires a starting cursor and event details. ```rust let usdc_address = starknet::FieldElement::from_hex( "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", )?; let transfer_hash = starknet::FieldElement::from_hex( "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9", )?; let request = StreamDataRequestBuilder::new() .with_starting_cursor(start_block) .add_filter( starknet::FilterBuilder::new() .add_event( starknet::EventFilterBuilder::single_contract(usdc_address) .with_keys(true, vec![Some(transfer_hash)]) .with_transaction() .build(), ) .build(), ) .build(); let mut stream = client.stream_data(request).await?; while let Some(message) = stream.try_next().await? { // Process the message here } ``` -------------------------------- ### Build All Crates with Nix Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Build all project crates using Nix to ensure they compile correctly within the Nix environment. This is a prerequisite before submitting a Pull Request. ```bash nix build .#all-crates ``` -------------------------------- ### Building Metadata Manually Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Demonstrates how to construct a MetadataMap and insert both static and computed values. Ensure values are parsed correctly. ```rust use apibara_sdk::{MetadataMap, MetadataKey, MetadataValue}; let mut metadata = MetadataMap::new(); // Insert static values metadata.insert("x-version", "1.0".parse()?); // Insert computed values let key = "x-client-id".parse::()?; let value = "my-app".parse::()?; metadata.insert(key, value); ``` -------------------------------- ### Add Custom Request ID to Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Example of adding a unique request ID to the metadata for tracking requests. ```rust use apibara_sdk::{StreamClientBuilder, MetadataMap}; use uuid::Uuid; let request_id = Uuid::new_v4().to_string(); let mut metadata = MetadataMap::new(); metadata.insert("x-request-id", request_id.parse()?); let client = StreamClientBuilder::new() .with_metadata(metadata) .connect(url) .await?; ``` -------------------------------- ### Build Integration Tests Archive with Nix Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Build a nextest archive for integration tests using Nix. This is the first step in running integration tests, which require connecting to the Docker daemon. ```bash nix build .#integration-tests-archive ``` -------------------------------- ### Establish a Basic Connection Source: https://github.com/apibara/dna/blob/main/_autodocs/README.md Connect to the Apibara API using a bearer token from environment variables. This is the initial step to interact with the streaming service. ```rust use apibara_sdk::{StreamClientBuilder, BearerTokenFromEnv}; use std::sync::Arc; let mut client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(BearerTokenFromEnv::default())) .connect("https://api.apibara.com".parse()?) .await?; ``` -------------------------------- ### Async/Await for I/O Operations Source: https://github.com/apibara/dna/blob/main/_autodocs/API-surface.md Illustrates the use of asynchronous programming with Tokio for establishing connections and streaming data. ```rust let client = builder.connect(url).await?; let stream = client.stream_data(request).await?; ``` -------------------------------- ### Starknet-Specific Filters Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Demonstrates how to build Starknet-specific filters using `FilterBuilder` and `EventFilterBuilder` for event tracking and transaction filtering. ```APIDOC ## Starknet-Specific API ### Description Provides an example of how to construct Starknet-specific filters using the SDK. This includes building filters for events emitted by a particular contract, with options to include transaction details and specific event keys. ### Feature Gate Requires the `starknet` feature for the `apibara-sdk` crate: `apibara-sdk = { features = ["starknet"] }` ### Code Example ```rust use apibara_sdk::starknet::{FilterBuilder, EventFilterBuilder, FieldElement}; let filter = FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(contract_address) .with_keys(true, vec![Some(event_key)]) .with_transaction() .build() ) .build(); ``` ### Filter Builders Overview - `FilterBuilder`: Root filter, combines all filter types. - `EventFilterBuilder`: Filters events by contract and key. - `TransactionFilterBuilder`: Filters transactions by type. - `MessageToL1FilterBuilder`: Filters messages sent to L1. - `StorageDiffFilterBuilder`: Filters state changes (storage diffs). - `ContractChangeFilterBuilder`: Filters contract lifecycle events. - `NonceUpdateFilterBuilder`: Filters nonce updates. ``` -------------------------------- ### Connect to Server with StreamClientBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md Use this snippet to establish a basic connection to the Apibara server using the `StreamClientBuilder`. Ensure you have the `apibara_sdk` crate imported. ```rust use apibara_sdk::StreamClientBuilder; let url = "https://api.apibara.com:443" .parse::()?; let client = StreamClientBuilder::new() .connect(url) .await?; ``` -------------------------------- ### StreamDataRequest Structure Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Defines the parameters for requesting a data stream, including starting point, finality, filters, and heartbeat interval. ```rust pub struct StreamDataRequest { pub starting_cursor: Option, pub finality: Option, pub filter: Vec>, pub heartbeat_interval: Option, } ``` -------------------------------- ### Get Service Status Source: https://github.com/apibara/dna/blob/main/sdk/README.md Retrieves the current status of the Apibara DNA service, including the last ingested block information. ```rust let status = client .status() .await?; let last_ingested = status.last_ingested.unwrap_or_default(); ``` -------------------------------- ### Authentication with Environment Variable Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Configures authentication using the `DNA_TOKEN` environment variable, which is the recommended method for providing API keys. ```APIDOC ## Authentication Option 1: Environment Variable (Recommended) ### Description Configures the SDK to use an API key stored in an environment variable. This is the recommended approach for managing sensitive credentials. ### Usage 1. **Set Environment Variable:** ```bash export DNA_TOKEN="your-api-key" ``` 2. **Use in Code:** ```rust use apibara_sdk::BearerTokenFromEnv; let provider = BearerTokenFromEnv::default(); // Reads from DNA_TOKEN // Or specify a custom environment variable name: let provider = BearerTokenFromEnv::new_with_var_name("MY_API_KEY".to_string()); ``` ``` -------------------------------- ### Create StreamClientBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client.md Use the builder pattern to configure and create a StreamClient instance. ```rust use apibara_sdk::StreamClient; let client = StreamClient::builder() .connect(url) .await?; ``` -------------------------------- ### Run Unit Tests with Nix Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Execute unit tests using Nix. This command runs tests within the same environment that will be used in GitHub Actions, ensuring consistency. ```bash nix build .#unit-tests ``` -------------------------------- ### Run Integration Tests Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Run integration tests from the previously built archive. This command is executed within the development shell provided by Nix. ```bash nix develop .#integration -c run-integration-tests ``` -------------------------------- ### Build Starknet Filter Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Creates a Starknet-specific filter for streaming events from a particular contract address with optional keys and transaction details. Requires the 'starknet' feature for the SDK. ```rust use apibara_sdk::starknet::{FilterBuilder, EventFilterBuilder, FieldElement}; let filter = FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(contract_address) .with_keys(true, vec![Some(event_key)]) .with_transaction() .build() ) .build(); ``` -------------------------------- ### Add Event Filter to FilterBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md Add an event filter to the main filter. This example creates an event filter for a single specified contract address. ```rust FilterBuilder::new() .add_event( EventFilterBuilder::single_contract(contract_address) .build() ) ``` -------------------------------- ### Add apibara-sdk Dependency Source: https://github.com/apibara/dna/blob/main/_autodocs/API-surface.md Include the main SDK crate in your project's dependencies. ```toml [dependencies] apibara-sdk = "0.4" ``` -------------------------------- ### Enable Starknet Feature Source: https://github.com/apibara/dna/blob/main/_autodocs/starknet-filters.md To use Starknet support, ensure the 'starknet' feature is enabled for the apibara-sdk dependency in your Cargo.toml file. ```toml [dependencies] apibara-sdk = { version = "0.4", features = ["starknet"] } ``` -------------------------------- ### StreamDataRequestBuilder::new() Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-data-request.md Creates a new StreamDataRequestBuilder with default settings. The default finality is DataFinality::Accepted, starting from genesis, with no filters, and no heartbeat interval set. ```APIDOC ## StreamDataRequestBuilder::new() ### Description Create a new builder with default accepted finality. ### Returns `StreamDataRequestBuilder` — A new builder with `DataFinality::Accepted` as default. ### Default Configuration: - Finality: `Accepted` - Starting cursor: `None` (starts from genesis) - Filters: empty - Heartbeat interval: not set (will default to timeout / 2 in StreamClient) ### Example: ```rust use apibara_sdk::StreamDataRequestBuilder; let request = StreamDataRequestBuilder::new() .with_starting_cursor(Some(cursor)) .build(); ``` ``` -------------------------------- ### Build StreamDataRequest Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Constructs a request to specify the data to be streamed. This includes setting the starting cursor, data finality level, chain-specific filters, and heartbeat interval. ```APIDOC ## Build a Request ### Description Builds a `StreamDataRequest` object, which defines the parameters for the data stream. This includes specifying the data finality, an optional starting cursor for resuming a stream, and applying one or more filters to select the desired data. ### Code Example ```rust use apibara_sdk::StreamDataRequestBuilder; use apibara_dna_protocol::dna::stream::DataFinality; let request = StreamDataRequestBuilder::new() .with_finality(DataFinality::Finalized) .with_starting_cursor(Some(cursor)) .add_filter(your_filter) .build(); ``` ``` -------------------------------- ### StreamClientBuilder Options Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Lists the available configuration options for the `StreamClientBuilder`, including authentication, metadata, timeouts, and maximum message size. ```APIDOC ## StreamClientBuilder Options ### Description Provides a list of configuration options available for the `StreamClientBuilder` to customize the connection and client behavior. These options control aspects like authentication, custom headers, message timeouts, and maximum message size. ### Options Table | Method | Type | Default | Purpose | |--------|------|---------|---------| | `with_bearer_token_provider()` | `Arc` | None | Authentication | | `with_metadata()` | `MetadataMap` | Empty | Custom headers | | `with_timeout()` | `Duration` | 60s | Message timeout | | `with_max_message_size_bytes()` | `usize` | Unlimited | Size limit | ``` -------------------------------- ### Build a StreamDataRequest Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Constructs a request to stream data, specifying finality, a starting cursor for resuming, and custom filters. Multiple filters can be added using `add_filter()`. ```rust use apibara_sdk::StreamDataRequestBuilder; use apibara_dna_protocol::dna::stream::DataFinality; let request = StreamDataRequestBuilder::new() .with_finality(DataFinality::Finalized) .with_starting_cursor(Some(cursor)) .add_filter(your_filter) .build(); ``` -------------------------------- ### Rust gRPC Client with Custom Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/grpc-endpoints.md Shows how to configure a gRPC client in Rust to include custom metadata, such as a client ID, in all requests. Requires the `tonic::metadata::MetadataMap` type. ```rust use tonic::metadata::MetadataMap; let mut metadata = MetadataMap::new(); metadata.insert("x-client-id", "my-indexer".parse()?); let client = StreamClientBuilder::new() .with_metadata(metadata) .connect(url) .await?; ``` -------------------------------- ### StreamClientBuilder::connect() Source: https://github.com/apibara/dna/blob/main/_autodocs/stream-client-builder.md Connects to the server using the provided URL and returns a configured StreamClient ready for streaming data. It handles potential connection and authentication errors. ```APIDOC ## StreamClientBuilder::connect() ### Description Connects to the server and return a ready-to-use `StreamClient`. ### Method `connect(self, url: Uri)` ### Parameters #### Path Parameters - **url** (`Uri`) - Required - Server URL (e.g., `https://localhost:50051`, `https://api.apibara.com`) ### Returns `Result` — A configured client ready to stream data. ### Throws - `StreamClientBuilderError::Connection`: Failed to establish TLS connection or network error. - `StreamClientBuilderError::BearerToken`: Bearer token provider failed to provide a token. ### Example ```rust use apibara_sdk::StreamClientBuilder; let url = "https://api.apibara.com:443" .parse::()?; let client = StreamClientBuilder::new() .connect(url) .await?; ``` ``` -------------------------------- ### Stream Iteration with DataStream Source: https://github.com/apibara/dna/blob/main/_autodocs/API-surface.md Demonstrates how to iterate over a `DataStream` to process incoming messages, showing both `while let` and `StreamExt::try_next` patterns. ```rust while let Some(result) = stream.next().await { match result { } } // Or with StreamExt::try_next: while let Some(message) = stream.try_next().await? { // message: DnaMessage } ``` -------------------------------- ### Apibara SDK with Starknet Features Source: https://github.com/apibara/dna/blob/main/_autodocs/README.md Enable the 'starknet' feature for the Apibara SDK to include Starknet-specific filter builders and types. This is necessary for Starknet-related development. ```toml apibara-sdk = { version = "0.4", features = ["starknet"] } ``` -------------------------------- ### StatusResponse Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Response containing server status information, including the current chain head, last ingested block, finalized block, and the starting block available in the node. ```APIDOC ## StatusResponse ### Description Response containing server status information. ### Fields - **current_head** (`Option`) - Required - Current head of the chain - **last_ingested** (`Option`) - Required - Last block ingested by the node - **finalized** (`Option`) - Required - Latest finalized block - **starting** (`Option`) - Required - First block available in node ### Example ```rust let status = client.status().await?; let last_ingested = status.last_ingested.unwrap_or_default(); println!("Last block: {}", last_ingested.order_key); ``` ``` -------------------------------- ### Propagating BearerTokenError in StreamClientBuilder Source: https://github.com/apibara/dna/blob/main/_autodocs/error-types.md Shows how BearerTokenError is wrapped within StreamClientBuilderError when encountered during the connection process. This example demonstrates accessing the underlying authentication error from the builder's error. ```rust match builder.connect(url).await { Err(StreamClientBuilderError::BearerToken { source }) => { // BearerTokenError is wrapped here eprintln!("Auth failed: {}", source); } _ => {} // Handle other potential errors } ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Configure the `tracing` crate to enable debug-level logging for the Apibara SDK. This is essential for diagnosing issues and understanding the SDK's internal operations. ```rust use tracing_subscriber; tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .init(); ``` -------------------------------- ### StatusResponse Struct Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Represents the server's status information, including the current chain head, last ingested block, finalized block, and the starting block available on the node. ```rust pub struct StatusResponse { pub current_head: Option, pub last_ingested: Option, pub finalized: Option, pub starting: Option, } ``` -------------------------------- ### Create MetadataInterceptor with Custom Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Factory method to create a MetadataInterceptor with a pre-defined set of metadata. Useful for setting initial headers. ```rust use apibara_sdk::MetadataInterceptor; use tonic::metadata::MetadataMap; let mut metadata = MetadataMap::new(); metadata.insert("x-trace-id", "abc123".parse()?); let interceptor = MetadataInterceptor::with_metadata(metadata); ``` -------------------------------- ### DataFinality Methods Source: https://github.com/apibara/dna/blob/main/_autodocs/protocol-types.md Provides methods to check the status of DataFinality. Use these to programmatically determine if data is pending, accepted, or finalized. ```rust impl DataFinality { pub fn is_pending(&self) -> bool pub fn is_accepted(&self) -> bool pub fn is_finalized(&self) -> bool } ``` -------------------------------- ### Handling DataStreamError during Streaming Source: https://github.com/apibara/dna/blob/main/_autodocs/error-types.md Provides a comprehensive example of handling various DataStreamError variants while iterating over a stream. It shows specific recovery actions for timeouts, gRPC errors (including checking status codes like PermissionDenied), and empty messages. ```rust use tokio_stream::StreamExt; while let Some(result) = stream.next().await { match result { Ok(message) => { // Process message } Err(DataStreamError::Timeout { elapsed }) => { eprintln!("Stream timeout after {:?}", elapsed); // Reconnect break; } Err(DataStreamError::Tonic { source }) => { eprintln!("gRPC error: {} (code: {:?})", source, source.code()); // Handle based on code if source.code() == tonic::Code::PermissionDenied { eprintln!("Authentication failed"); } break; } Err(DataStreamError::EmptyMessageInResponse) => { eprintln!("Received empty message (server error?)"); break; } } } ``` -------------------------------- ### Add Multi-Tenant Identification to Metadata Source: https://github.com/apibara/dna/blob/main/_autodocs/metadata.md Demonstrates adding tenant and user IDs to metadata for multi-tenant applications. ```rust let mut metadata = MetadataMap::new(); metadata.insert("x-tenant-id", "tenant-123".parse()?); metadata.insert("x-user-id", "user-456".parse()?); let client = StreamClientBuilder::new() .with_metadata(metadata) .connect(url) .await?; ``` -------------------------------- ### Create Test Cursor Source: https://github.com/apibara/dna/blob/main/_autodocs/chain-integrations.md Utility for creating a test cursor, useful for testing filter logic without a running node. ```rust use apibara_dna_common::testing::new_test_cursor; let cursor = new_test_cursor(12345); ``` -------------------------------- ### Into Conversion Usage Source: https://github.com/apibara/dna/blob/main/_autodocs/API-surface.md Shows how methods can accept types that implement `Into`, allowing for automatic conversion from builders or direct types. ```rust pub async fn stream_data( &mut self, request: impl Into, ) -> Result // Usage: client.stream_data(builder).await?; // Automatic conversion client.stream_data(request).await?; // Direct type ``` -------------------------------- ### Optional Authentication with Environment Variable Check Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Conditionally connect using a bearer token if DNA_TOKEN is set, otherwise connect without authentication. This allows for flexible authentication strategies. ```rust let client = if let Ok(token) = std::env::var("DNA_TOKEN") { StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(StaticBearerToken::new(token))) .connect(url) .await? } else { StreamClientBuilder::new() .connect(url) .await? }; ``` -------------------------------- ### Initialize and Connect StreamClient Source: https://github.com/apibara/dna/blob/main/_autodocs/quick-reference.md Establishes a gRPC connection to the DNA service using a bearer token. It requires the DNA_TOKEN environment variable to be set with a valid API key and a valid URL for the DNA service. ```APIDOC ## Initialize and Connect StreamClient ### Description Initializes the `StreamClient` by establishing a gRPC connection to the DNA service. It supports authentication via bearer tokens, typically provided through environment variables. ### Requirements - `DNA_TOKEN` environment variable must be set with your API key. - A valid URL to the DNA service is required. ### Code Example ```rust use apibara_sdk::{StreamClientBuilder, BearerTokenFromEnv}; use std::sync::Arc; let mut client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(BearerTokenFromEnv::default())) .connect("https://api.apibara.com".parse()?) .await?; ``` ``` -------------------------------- ### Use BearerTokenFromEnv for Production Authentication Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Instantiate a BearerTokenProvider using the environment variable. This is suitable for production environments. ```rust let provider = BearerTokenFromEnv::default(); let client = StreamClientBuilder::new() .with_bearer_token_provider(Arc::new(provider)) .connect(url) .await?; ``` -------------------------------- ### BearerTokenFromEnv Construction (Default) Source: https://github.com/apibara/dna/blob/main/_autodocs/authentication.md Constructs a BearerTokenFromEnv provider that reads the token from the DNA_TOKEN environment variable. This is useful for default configurations. ```rust impl BearerTokenFromEnv { pub fn new() -> Self pub fn new_with_var_name(env_var_name: String) -> Self } impl Default for BearerTokenFromEnv { fn default() -> Self // Uses DNA_TOKEN env var } ``` -------------------------------- ### Clone Apibara Project Source: https://github.com/apibara/dna/blob/main/CONTRIBUTING.md Clone the Apibara project repository using Git. Choose the appropriate command based on your preferred Git protocol or GitHub CLI usage. ```bash git clone git@github.com:apibara/dna.git ``` ```bash # or git clone https://github.com/apibara/dna.git ``` ```bash # or gh repo clone apibara/dna ```