# Makers

> This endpoint is reserved for trading firms operating a prop AMM on Ethereum who want to land quote updates in Titan blocks. Access is API-key gated, please reach out if you want access.

### Behavioural properties

#### Maker priority

The builder provides two defences against being picked off on latency.

**Taker ordering.** When a taker trade against the pool is included in a block, the latest applicable quote update is guaranteed to be placed before it in the same block.

**Maker freshness protection.** A per-session freshness buffer `b`, set at onboarding, can be applied to takers routing against your pool. A taker is only eligible to trade against a quote update if the taker was received by the builder at least `b` before that quote update was received:

```
taker_recv + b < quote_update_recv
```

For example, with `b = 50ms`, a quote update received at time `T` can only be matched against takers received before `T - 50ms`.

This reduces exposure to toxic takers attempting to snipe stale quotes, while also protecting makers in case of quote streaming failures mid-slot.

#### Fast replacements and cancellations

Quotes sent through this endpoint take the fastest path to the builders. We have cores dedicated to simulating and applying these bundles efficiently. Cancellations are more consistent due to stricter block overwrite rules.

#### Conditional inclusion

Quote transactions can either land every block, or only when a taker in the block trades against the pool. The builder evaluates each candidate tx against every live quote and, in conditional mode, includes the latest quote update immediately before any matching taker - quotes that are never matched never go onchain.

### Authentication

Authentication uses an API key shared directly when access is granted. Specify it in the `Authorization` header when establishing the WebSocket connection.

### Endpoints

Use the following regional endpoints to get the lowest latency between your quote publisher and our clusters. Higher-performance URLs (direct access) are available on request.

| Region           | Endpoint                                           |
| ---------------- | -------------------------------------------------- |
| `eu-central-1`   | `wss://eu.rpc.titanbuilder.xyz/ws/sendquoteupdate` |
| `ap-northeast-1` | `wss://ap.rpc.titanbuilder.xyz/ws/sendquoteupdate` |
| `us-east-1`      | `wss://us.rpc.titanbuilder.xyz/ws/sendquoteupdate` |

### Submit quote (`ws/sendquoteupdate`)

```proto
message PWebsocketQuoteUpdateV1Args {
  // RLP-encoded quote-update tx bytes. Empty = cancel the replacement_uuid.
  bytes tx = 1;
  // single block this quote is valid for
  uint64 block_number = 2;
  // 16-byte quote identifier (raw UUID bytes).
  bytes replacement_uuid = 3;
  // monotonic per uuid (>0)
  uint64 replacement_seq_number = 4;
  // quotes will not be shared between builder regions
  bool disable_cross_region_sharing = 5;
}
```

`replacement_uuid` must be set and exactly 16 bytes. `replacement_seq_number` must be set and strictly greater than the previous value seen under the same `replacement_uuid` and cannot be 0. Messages violating either constraint are dropped.

We recommend setting `disable_cross_region_sharing` to `true`. Otherwise we broadcast your quotes internally across regions, which adds latency you do not control. For best results, run edge nodes next to each of our regional clusters and send directly to the closest.

### Cancel quotes

Send a `PWebsocketQuoteUpdateV1Args` with `tx` empty, `replacement_uuid` set to the quote you want to pull, and a strictly greater `replacement_seq_number` than the last update under that uuid.

### Response

```proto
message PWebsocketQuoteUpdateV1Response {
  // Quote identifier being acknowledged.
  bytes replacement_uuid = 1;
  uint64 replacement_seq_number = 2;
  // RPC receive UNIX nanos.
  uint64 timestamp = 3;
  // Empty on success. Populated with error detail on failure.
  string error = 4;
}
```

Match responses to submits on `(replacement_uuid, replacement_seq_number)`. Use `timestamp` minus your local send-time to measure end-to-end latency.

### Example (Rust)

```rust
// Generate the `pb` module from the .proto above using prost-build.

use std::io::ErrorKind;
use tungstenite::{client::IntoClientRequest, stream::MaybeTlsStream, Message as WsMessage};
use prost::Message;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut req = "wss://eu.rpc.titanbuilder.xyz/ws/sendquoteupdate".into_client_request()?;
    req.headers_mut().insert("Authorization", "YOUR_API_KEY".parse()?);

    let (mut ws, _) = tungstenite::connect(req)?;

    if let MaybeTlsStream::Plain(s) = ws.get_mut() {
        s.set_nodelay(true)?;
        s.set_nonblocking(true)?;
    }

    let mut buf = Vec::with_capacity(4096);
    let mut seq: u64 = 0;

    loop {
        seq += 1;
        let quote = pb::PWebsocketQuoteUpdateV1Args {
            tx: vec![/* RLP-encoded signed quote-update tx */],
            block_number: 1234,
            replacement_uuid: vec![/* 16 bytes */],
            replacement_seq_number: seq,
            disable_cross_region_sharing: true,
        };

        buf.clear();
        quote.encode(&mut buf)?;

        match ws.send(WsMessage::Binary(buf.into())) {
            Ok(()) => {}
            Err(tungstenite::Error::Io(e)) if e.kind() == ErrorKind::WouldBlock => {}
            Err(e) => return Err(e.into()),
        }

        match ws.read() {
            Ok(WsMessage::Binary(bytes)) => {
                let _resp = pb::PWebsocketQuoteUpdateV1Response::decode(&*bytes)?;
                // latency = match on (replacement_uuid, replacement_seq_number)
            }
            Ok(_) => {}
            Err(tungstenite::Error::Io(e)) if e.kind() == ErrorKind::WouldBlock => {}
            Err(e) => return Err(e.into()),
        }
    }
}
```

### Pricing

Quote updates submitted through this endpoint do not pay priority fees.

Instead, makers are charged a volume-based fee on filled trades. Fees are configured on a per-pair basis. Pricing may differ across assets depending on market structure and quoting behaviour, though fees across makers are the same.

During the initial testing phase, fee discounts are active while we collect data on spreads, fill quality, and realised markouts across different markets. We expect to move to a more stable and publicly documented fee schedule once the system has been sufficiently tested and pricing can be calibrated from production data. Please reach out directly for more information on current pricing.

### Permissionless Access

We're also exploring opening these guarantees up permissionlessly. For example, we are exploring supporting this initiative: <https://github.com/flashbots/priority-update-registry>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.titanbuilder.xyz/propamms/makers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
