# Takers

> Audience: searchers, solvers, and aggregators routing flow or arbitrage paths through pAMM liquidity in Titan blocks.

### Multi-candidate bundle submission

Send us N candidate bundles for the same trade, each routing differently. At build time we evaluate every candidate against live state, including the freshest streamed quote from every pAMM, and include whichever gives the best outcome.

* Construct your normal path through CFMM liquidity.
* Construct additional variants where one or more hops route through pAMMs.
* Submit all variants. We evaluate each against current state at build time and re-evaluate on every pAMM quote update until inclusion.

Use the same bundle submission path you already use.

### pAMM state stream

Takers can consume a JSON stream of pAMM state overrides for makers that opt in to publishing their state. The stream is intended for searchers, solvers, and dex aggregators that want fresher routing inputs for pAMM liquidity before submitting candidate bundles.

The stream is maker opt-in. Makers choose whether to publish state, and configure the update thresholds and delay applied before state is emitted.

Some maker streams may require permissioned access. For example, a maker may only allow whitelisted takers such as dex aggregators to consume their stream. Please reach out if there are pAMM quotes you want access to that are not currently available.

### pAMM stream addresses

Current expected top-level stream addresses:

| Protocol  | Top-level stream address                     | Simulator call target                                                                     | Oracle touched in `state_override`           |
| --------- | -------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------- |
| FermiSwap | `0xb1076fe3ab5e28005c7c323bac5ac06a680d452e` | `quoteAmounts(...)` on `0xb1076fe3ab5e28005c7c323bac5ac06a680d452e`                       | `0x0bA5665583A4593A86cdC935ea2c8FF378c11317` |
| Kipseli   | `0x5cdbe59400cc2efdcc2b54acca4a99fe00dd588c` | `swap(...)` on `0x5cdbe59400cc2efdcc2b54acca4a99fe00dd588c` with a token balance override | `0x8051c111cd6978396e4f81cd81d21b1ae8be5a08` |
| bopAMM    | `0x160141a205f5ddcf096ba3f48b7ed21eb52c62ea` | `quote(...)` on `0x160141a205f5ddcf096ba3f48b7ed21eb52c62ea`                              | `0x160141a205f5ddcf096ba3f48b7ed21eb52c62ea` |

The public no-auth stream currently exposes FermiSwap and Kipseli and excludes bopAMM.

#### Endpoints

| Region         | WebSocket endpoint                                   | JSON-RPC endpoint                 |
| -------------- | ---------------------------------------------------- | --------------------------------- |
| eu-central-1   | `wss://eu.rpc.titanbuilder.xyz/ws/pamm_quote_stream` | `https://eu.rpc.titanbuilder.xyz` |
| ap-northeast-1 | `wss://ap.rpc.titanbuilder.xyz/ws/pamm_quote_stream` | `https://ap.rpc.titanbuilder.xyz` |
| us-east-1      | `wss://us.rpc.titanbuilder.xyz/ws/pamm_quote_stream` | `https://us.rpc.titanbuilder.xyz` |

#### Format

Each WebSocket message is JSON. Every other top-level key is a pAMM quote stream address. The value is an object with a `stateOverride` field.

```json
{
  "slot": 14285824,
  "blockNumber": 25051224,
  "timestamp": 1778253913749564761,
  "0xb1076fe3ab5e28005c7c323bac5ac06a680d452e": {
    "stateOverride": {
      "0x1038c87766e36d1925889e6f26d10e0012d50fed": {
        "balance": "0x0",
        "nonce": "0x1",
        "stateDiff": {
          "0x156b1d71de08fed89d0fce38008e2b9d03a8998077e394b20597ef3d148f5ebc": "0x000000000000000000000000000000000000000000000000000000017e405801"
        }
      }
    }
  }
}

```

`stateOverride` uses the same structure as the Ethereum eth\_call State Override Set.

The keys inside `stateOverride` are Ethereum account addresses. Each account override may include:

* balance&#x20;
* nonce&#x20;
* code&#x20;
* state&#x20;
* stateDiff

`stateDiff` maps storage slot keys to overridden storage values.

The object can be passed directly as the third parameter to `eth_call` or `eth_simulateV1`.

If a taker has access to multiple pAMM feeds, Titan merges all maker updates into a single flat `stateOverride` object keyed by account address.

#### Latest state over JSON-RPC

Takers that do not want to maintain a WebSocket connection can request the latest flattened pAMM state view over JSON-RPC.

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "titan_getPammStateOverrides",
  "params": []
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "blockNumber": "0x16f3a10",
    ...
  }
}
```

#### Example (Python)

```python
import asyncio
import json
import urllib.request
import websockets

WS_URI = "wss://eu.rpc.titanbuilder.xyz/ws/pamm_quote_stream"
RPC_URL = "https://eu.rpc.titanbuilder.xyz/"


def get_pamm_state_overrides():
    body = json.dumps({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "titan_getPammStateOverrides",
        "params": [],
    }).encode()
    req = urllib.request.Request(
        RPC_URL, data=body, headers={"Content-Type": "application/json"}
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read())["result"]


async def main():
    # One-shot snapshot.
    snapshot = get_pamm_state_overrides()
    print(int(snapshot["blockNumber"], 16), snapshot["stateOverrides"])
    
    # Live updates.
    async with websockets.connect(WS_URI) as ws:
        async for message in ws:
            update = json.loads(message)
            block_number = int(update["block_number"])
            state_overrides = update["state_override"]
            print(block_number, state_overrides)


asyncio.run(main())
```

### On-chain routing

On-chain routing is another integration path for pAMM liquidity. This is not a separate Titan endpoint, but a router or solver-side pattern that can be used alongside the bundle flow above.

The idea is to move route selection into the execution transaction. Instead of submitting a single pre-selected path, the transaction could carry multiple candidates per hop. For a route from asset A to asset B to asset C, the A → B hop could have several candidate venues, and the B → C hop could have several candidate venues. Some candidates may route through standard AMM liquidity, while others may route through pAMMs.

Because execution happens onchain, the router evaluates the candidate set against the exact execution state and selects the best valid combination. This is especially attractive for pAMM routing because quote state can change between path construction and inclusion. If a maker update lands earlier in the same block, the router sees the updated state when the taker transaction executes.


---

# 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/takers.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.
