> For the complete documentation index, see [llms.txt](https://docs.substreams.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.substreams.dev/how-to-guides/develop-your-own-substreams/general/creating-protobuf-schemas.md).

# Protobuf

StreamingFast Substreams protobuf schemas

## Protobuf overview

Substreams uses Google Protocol Buffers extensively. Protocol Buffers, also referred to as protobufs, are used as the API for data models specific to the different blockchains. Manifests contain references to the protobufs for your Substreams module.

{% hint style="success" %}
**Tip**: Protobufs define the input and output for modules.
{% endhint %}

{% hint style="info" %}
**Tip**: The [substreams-dev agent skill](/how-to-guides/develop-your-own-substreams/general/agent-skills.md) includes expert knowledge on protobuf schema design for blockchain data modeling — install it in your AI coding assistant to get guidance while designing your schemas.
{% endhint %}

Learn more about the details of Google Protocol Buffers in the official documentation provided by Google.

**Google Protocol Buffer Documentation**

[Learn more about Google Protocol Buffers](https://protobuf.dev/) in the official documentation provided by Google.

**Google Protocol Buffer Tutorial**

[Explore examples and additional learning material](https://protobuf.dev/programming-guides/proto3/) for Google Protocol Buffers provided by Google.

### Protobuf definition for Substreams

Define a protobuf model as [`proto:eth.erc721.v1.Transfers`](https://github.com/streamingfast/substreams-template/blob/develop/proto/erc721.proto) representing a list of ERC721 transfers.

{% hint style="info" %}
**Note**: The `Transfers` protobuf in the Substreams Template example is located in the proto directory.
{% endhint %}

{% code title="eth/erc721/v1/erc721.proto" lineNumbers="true" %}

```protobuf
syntax = "proto3";

package eth.erc721.v1;

message Transfers {
  repeated Transfer transfers = 1;
}

message Transfer {
  bytes from = 1;
  bytes to = 2;
  uint64 token_id = 3;
  bytes trx_hash = 4;
  uint64 ordinal = 5;
}
```

{% endcode %}

[View the `erc721.proto`](https://github.com/streamingfast/substreams-template/blob/develop/proto/erc721.proto) file in the official Substreams Template example repository.

#### Identifying data types

The ERC721 smart contract used in the Substreams Template example contains a `Transfer` event. You can use the event data through a custom protobuf.

The protobuf file serves as the interface between the module handlers and the data being provided by Substreams.

{% hint style="success" %}
**Tip**: Protobufs are platform-independent and are defined and used for various blockchains.

* The ERC721 smart contracts used in the Substreams Template example are generic contracts used across many different Ethereum applications.
* The size and scope of the Substreams module dictates the number of and complexity of protobufs.
  {% endhint %}

The Substreams Template example extracts `Transfer` events from the [Bored Ape Yacht Club smart contract](https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d) which is located on the Ethereum blockchain.

Several specific data types exist in the Ethereum smart contract ecosystem, some extending the ERC20 and ERC721 base modules. Complex protobufs are created and refined based on the various data types used across the different blockchains.

{% hint style="success" %}
**Tip***:* The use of fully qualified protobuf file paths reduces the risk of naming conflicts when other community members build their [Substreams packages](/reference-material/manifest-and-components/packages.md#dependencies).
{% endhint %}

### Generating protobufs

The [`substreams` CLI](/reference-material/command-line-interface.md) is used to generate the associated Rust code for the protobuf.

Notice the `protogen` command and Substreams manifest passed into the [`substreams` CLI](/reference-material/command-line-interface.md).

{% code overflow="wrap" %}

```bash
substreams protogen ./substreams.yaml --exclude-paths="sf/ethereum,sf/substreams,google"
```

{% endcode %}

The pairing code is generated and saved into the [`src/pb/eth.erc721.v1.rs`](https://github.com/streamingfast/substreams-template/blob/develop/src/pb/eth.erc721.v1.rs)Rust file.

The [`mod.rs`](https://github.com/streamingfast/substreams-template/blob/develop/src/pb/mod.rs) file located in the `src/pb` directory of the Substreams Template example is responsible for exporting the freshly generated Rust code.

{% code title="src/pb/mod.rs" overflow="wrap" lineNumbers="true" %}

```rust
// @generated by substreams
#![allow(clippy::all)]
pub mod eth {
    pub mod erc721 {
        pub mod v1 {
            include!("eth.erc721.v1.mod.rs");
        }
    }
}
```

{% endcode %}

View the [`mod.rs`](https://github.com/streamingfast/substreams-template/blob/develop/src/pb/mod.rs) file in the repository.

`substreams build` writes this file for you, with one `pub mod` per protobuf package segment wrapping an `include!` of the file the plugin generated. A `mod.rs` the CLI did not write is left untouched, so you can hand-edit the module tree and keep your changes across rebuilds.

### Protobuf and Rust optional fields

Protocol buffers define fields' type by using standard primitive data types, such as integers, booleans, and floats or a complex data type such as `message`, `enum`, `oneof` or `map`. View the [full list](https://developers.google.com/protocol-buffers/docs/proto#scalar) of types in the [Google Protocol Buffers documentation](https://developers.google.com/protocol-buffers/docs/overview).

Any primitive data types in a message generate the corresponding Rust type,[`String`](https://doc.rust-lang.org/std/string/struct.String.html) for `string`, `u64` for `uint64,` and assign the default value of the corresponding Rust type if the field is not present in a message, an empty string for [`String`](https://doc.rust-lang.org/std/string/struct.String.html), 0 for integer types, `false` for `bool`.

A field referencing another `message` generates a [`MessageField<T>`](https://docs.rs/buffa/latest/buffa/struct.MessageField.html), which dereferences to a default instance of `T` when the field is absent. Read through it directly:

```rust
let city = person.location.city; // "" when location is absent
```

This makes the common case total: a missing sub-message yields zero values rather than panicking, so a handler does not need to guard every nested access.

Where presence itself carries meaning, test for it explicitly:

```rust
if person.location.is_set() {
    // The message set this field, do something
}
```

To work with the field as a standard Rust [`Option`](https://doc.rust-lang.org/rust-by-example/std/option.html), call `as_option()` for a borrow or `into_option()` to take it by value:

```rust
match person.location.as_option() {
    Some(location) => { /* Value is present, do something */ }
    None => { /* Value is absent, do something */ }
}
```

Construct the field with `MessageField::some(value)`, and clear it with `MessageField::none()`.

[buffa](https://github.com/anthropics/buffa) is the tool that generates this Rust code from your protobuf definitions. `substreams build` runs it for you.
