> ## Documentation Index
> Fetch the complete documentation index at: https://docs.p2p.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Wire Formats & BCS Conventions

> Wire formats and BCS conventions used by the Syncro Sui data endpoints.

For every route below, two equivalent descriptions are given:

* **Rust client**: code snippet assuming you depend on `sui-types` (and `consensus-core` for `/v1/accepted`).
* **Raw BCS schema**: structural description for clients that cannot import Sui crates.

The raw schemas reference sui-types primitives (`SenderSignedData`, `TransactionEffects`, `TransactionEvents`, etc.) which are themselves complex nested BCS types. The canonical authoritative definitions live in the Sui source tree under `crates/sui-types/src/`; many language ecosystems also ship Sui-SDK packages with type-equivalent decoders.

## BCS encoding conventions

* Fields are emitted in struct-declaration order with no field names.
* Fixed-size `[u8; N]` arrays serialize as `N` length-prefixed bytes — the length prefix is a ULEB128 byte (`0x20` for 32-byte digests).
* `u8/u16/u32/u64` are little-endian.
* `Vec<T>` = ULEB128 length, then `length` consecutive `T` values.
* `Option<T>` = `0x00` (None) or `0x01 <T>` (Some).
* Enums = ULEB128 variant index, then variant payload.
* `String` = `Vec<u8>` (UTF-8 bytes with a length prefix).

## /v1/incoming — BCS Transaction

Each WS frame is one BCS-encoded `sui_types::transaction::Transaction`, byte-identical to the bytes the submitting client sent to the validator’s gRPC endpoint.

`Transaction` is `Envelope<SenderSignedData, EmptySignInfo>`. `EmptySignInfo` is a zero-sized unit struct, so the on-wire bytes equal a bare `SenderSignedData`.

**Rust client**:

<CodeGroup>
  ```bash bash theme={null}
  use sui_types::transaction::Transaction;

  let tx: Transaction = bcs::from_bytes(&frame)?;
  let digest = tx.digest();                       // &TransactionDigest
  let sender = tx.transaction_data().sender();    // SuiAddress
  ```
</CodeGroup>

**Raw BCS schema**:

<CodeGroup>
  ```bash bash theme={null}
  Transaction := SenderSignedData

  SenderSignedData := Vec<SenderSignedTransaction>

  SenderSignedTransaction := {
      intent_message:  IntentMessage<TransactionData>,
      tx_signatures:   Vec<GenericSignature>,
  }

  IntentMessage<T> := {
      intent: Intent (3 bytes — scope, version, app_id, each u8),
      value:  T,
  }
  ```
</CodeGroup>

`TransactionData`, `GenericSignature`, etc. are defined in `sui-types/src/transaction.rs` and `sui-types/src/crypto.rs`. Most Sui SDKs already include decoders.

## /v1/accepted — BCS SignedBlock

Each WS frame is one BCS-encoded `consensus_core::block::SignedBlock` — exactly the bytes the validator received on the wire from a peer. One block contains many transactions; each transaction inside is itself a BCS-encoded `ConsensusTransaction`.

**Rust client (using consensus-core’s helper)**:

<CodeGroup>
  ```bash bash theme={null}
  use sui_types::messages_consensus::ConsensusTransaction;
  use consensus_core::extract_transactions_from_signed_block_bytes;

  let raw_txs = extract_transactions_from_signed_block_bytes(&frame)?;
  for raw in raw_txs {
      let consensus_tx: ConsensusTransaction = bcs::from_bytes(&raw)?;
      if let Some(user_tx) = consensus_tx.kind.into_user_transaction() {
          let digest = user_tx.digest();
          let sender_signed = user_tx.into_data();
          // … your processing …
      }
      // else: system message, skip
  }
  ```
</CodeGroup>

**Raw BCS schema**:

<CodeGroup>
  ```bash bash theme={null}
  SignedBlock := {
      inner:     Block,
      signature: Vec<u8>,    // BCS Bytes — length-prefixed
  }

  Block := enum {
      0x00: BlockV1,
      0x01: BlockV2,
  }

  BlockV1 := {
      epoch:               u64,
      round:               u32,
      author:              u32,                  // AuthorityIndex
      timestamp_ms:        u64,
      ancestors:           Vec<BlockRef>,
      transactions:        Vec<ConsensusTx>,     // user/system txs in the block
      commit_votes:        Vec<CommitVote>,
      misbehavior_reports: Vec<MisbehaviorReport>,
  }

  BlockV2 := {
      epoch:               u64,
      round:               u32,
      author:              u32,
      timestamp_ms:        u64,
      ancestors:           Vec<BlockRef>,
      transactions:        Vec<ConsensusTx>,
      transaction_votes:   Vec<BlockTransactionVotes>,   // extra vs V1
      commit_votes:        Vec<CommitVote>,
      misbehavior_reports: Vec<MisbehaviorReport>,
  }

  ConsensusTx := {
      data: Vec<u8>,    // BCS-encoded ConsensusTransaction (see below)
  }

  BlockRef := {
      round:  u32,
      author: u32,
      digest: [u8; 32],    // BCS: 0x20 prefix + 32 digest bytes
  }

  ConsensusTransaction := {
      tracking_id: [u8; 8],
      kind:        ConsensusTransactionKind,
  }

  ConsensusTransactionKind := enum {
      // … many system-message variants — skip …
      UserTransaction(Transaction),                      // legacy V1
      UserTransactionV2(TransactionWithClaims),
      // … more system variants — skip …
  }

  TransactionWithClaims := {
      tx:     SenderSignedData,
      claims: Vec<TransactionClaim>,
  }
  ```
</CodeGroup>

The variant indices for `ConsensusTransactionKind` are stable; the exact index of `UserTransaction` and `UserTransactionV2` is defined in `sui-types/src/messages_consensus.rs`. Non-user variants can be skipped.

For each `UserTransaction*` you encounter, the inner `SenderSignedData` is identical in shape to the `/v1/incoming` payload.

`CommitVote, BlockTransactionVotes, MisbehaviorReport, TransactionClaim` are defined in `consensus-core/src/{block,commit}.rs` and `sui-types/src/messages_consensus.rs`.

## /v1/pending — BCS PendingTxStreamMessage

<CodeGroup>
  ```bash bash theme={null}
  pub struct PendingTxStreamMessage {
      pub tx_digest:          TransactionDigest,
      pub sender_signed_data: SenderSignedData,
      pub consensus_round:    u64,
      pub timestamp_ms:       u64,
  }
  ```
</CodeGroup>

**Rust client**:

<CodeGroup>
  ```javascript JavaScript theme={null}
  let msg: PendingTxStreamMessage = bcs::from_bytes(&frame)?;
  ```
</CodeGroup>

**Raw BCS schema**:

<CodeGroup>
  ```bash bash theme={null}
  PendingTxStreamMessage := {
      tx_digest:          [u8; 32],         // wire: 0x20 prefix + 32 bytes
      sender_signed_data: SenderSignedData, // same shape as /v1/incoming
      consensus_round:    u64,
      timestamp_ms:       u64,              // milliseconds since unix epoch
  }
  ```
</CodeGroup>

System transactions are filtered server-side and never appear on this stream.

## /v1/executed — BCS TxStreamMessage

<CodeGroup>
  ```bash bash theme={null}
  pub struct TxStreamMessage {
      pub tx_digest:          TransactionDigest,
      pub sender:             SuiAddress,
      pub sender_signed_data: SenderSignedData,
      pub effects:            TransactionEffects,
      pub events:             TransactionEvents,
      pub timestamp_ms:       u64,
  }
  ```
</CodeGroup>

**Rust client**:

<CodeGroup>
  ```javascript JavaScript theme={null}
  let msg: TxStreamMessage = bcs::from_bytes(&frame)?;
  ```
</CodeGroup>

**Raw BCS schema**:

<CodeGroup>
  ```bash bash theme={null}
  TxStreamMessage := {
      tx_digest:          [u8; 32],
      sender:             [u8; 32],          // SuiAddress
      sender_signed_data: SenderSignedData,
      effects:            TransactionEffects, // enum, versioned
      events:             TransactionEvents,
      timestamp_ms:       u64,
  }
  ```
</CodeGroup>

`TransactionEffects` is a versioned enum (`V1 / V2`); BCS encodes the variant index as a ULEB128 byte followed by the variant payload. `TransactionEvents` is `Vec<Event>`. Both are defined in `sui-types/src/effects.rs`.

System transactions are filtered server-side and never appear on this stream.


## Related topics

- [Submission & Versioning](/docs/syncro-data-sui-submission-and-versioning.md)
- [Stream Semantics](/docs/syncro-data-sui-stream-semantics.md)
