> For the complete documentation index, see [llms.txt](https://developers.lfj.gg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.lfj.gg/poe/discovering-pools.md).

# Discovering Pools

POE supports an unbounded number of pools — one per ordered `(tokenX, tokenY)` pair. Integrators do **not** have to hard-code each market: the `Factory` keeps a registry, so you can enumerate pools or look them up by pair on-chain.

The `Factory` address is the same on every supported chain (see POE Contracts):

```
Factory: 0x78120F2C0EBF0cc8B7E7749e62D36e6523dD711D
```

### Factory Lookup API

```solidity
interface IFactory {
    // Total number of pools ever created.
    function getPoolsLength() external view returns (uint256);

    // Index-based access. `poolId` is in [0, getPoolsLength()).
    function getPoolAt(uint256 poolId) external view returns (address);

    // Look up a pool by its ordered token pair. Returns address(0) if no pool exists.
    function getPool(address tokenX, address tokenY) external view returns (address);

    event PoolCreated(
        uint256 indexed poolId,
        address indexed pool,
        address tokenX,
        address tokenY,
        bytes data
    );
}
```

The pair ordering matters — `getPool(tokenY, tokenX)` is a different (typically non-existent) entry from `getPool(tokenX, tokenY)`. Use the same ordering the pool was created with.

### Listing every pool

Enumerate `[0, getPoolsLength())` and resolve each pool to its token pair:

```solidity
IFactory factory = IFactory(0x78120F2C0EBF0cc8B7E7749e62D36e6523dD711D);

uint256 n = factory.getPoolsLength();
for (uint256 i = 0; i < n; ++i) {
    address pool = factory.getPoolAt(i);
    (address tokenX, address tokenY) = IBasePool(pool).getTokens();
    // ...
}
```

The pool exposes the pair via `getTokens()` (returns the same `(tokenX, tokenY)` tuple the pool was initialized with) and its current balances via `getBalances()`. See Tracking Liquidity for the full pool read API.

#### TypeScript

```typescript
import { ethers } from 'ethers';

const FACTORY = '0x78120F2C0EBF0cc8B7E7749e62D36e6523dD711D';

const FACTORY_ABI = [
    'function getPoolsLength() view returns (uint256)',
    'function getPoolAt(uint256 poolId) view returns (address)',
    'function getPool(address tokenX, address tokenY) view returns (address)',
];

const POOL_ABI = [
    'function getTokens() view returns (address tokenX, address tokenY)',
    'function getBalances() view returns (uint256 totalX, uint256 totalY)',
];

async function listPools(provider: ethers.Provider) {
    const factory = new ethers.Contract(FACTORY, FACTORY_ABI, provider);
    const n: bigint = await factory.getPoolsLength();

    const pools = await Promise.all(
        Array.from({ length: Number(n) }, async (_, i) => {
            const address: string = await factory.getPoolAt(i);
            const pool = new ethers.Contract(address, POOL_ABI, provider);
            const { tokenX, totalX, tokenY, totalY } =
                Object.assign({}, await pool.getTokens(), await pool.getBalances());
            return { address, tokenX, tokenY, totalX, totalY };
        })
    );

    return pools;
}
```

#### Python

```python
from web3 import Web3

FACTORY = '0x78120F2C0EBF0cc8B7E7749e62D36e6523dD711D'

factory_abi = [
    {"name": "getPoolsLength", "type": "function", "inputs": [],
     "outputs": [{"type": "uint256"}], "stateMutability": "view"},
    {"name": "getPoolAt", "type": "function",
     "inputs": [{"name": "poolId", "type": "uint256"}],
     "outputs": [{"type": "address"}], "stateMutability": "view"},
    {"name": "getPool", "type": "function",
     "inputs": [{"name": "tokenX", "type": "address"},
                {"name": "tokenY", "type": "address"}],
     "outputs": [{"type": "address"}], "stateMutability": "view"},
]

pool_abi = [
    {"name": "getTokens", "type": "function", "inputs": [],
     "outputs": [{"name": "tokenX", "type": "address"},
                 {"name": "tokenY", "type": "address"}],
     "stateMutability": "view"},
]

def list_pools(w3: Web3):
    factory = w3.eth.contract(address=w3.to_checksum_address(FACTORY), abi=factory_abi)
    n = factory.functions.getPoolsLength().call()
    pools = []
    for i in range(n):
        address = factory.functions.getPoolAt(i).call()
        pool = w3.eth.contract(address=address, abi=pool_abi)
        token_x, token_y = pool.functions.getTokens().call()
        pools.append({"address": address, "token_x": token_x, "token_y": token_y})
    return pools
```

### Looking up a specific pair

If you already know the ordered pair, skip enumeration:

```solidity
address pool = factory.getPool(tokenX, tokenY);
require(pool != address(0), "No pool for this pair");
```

The first ordering you try may not match — pool creation pins a single direction. If `getPool(a, b)` returns zero, try `getPool(b, a)` before concluding the pair isn't listed.

### Reacting to new pools

Pool creation emits a `PoolCreated` event from the Factory. Indexers and integrators can subscribe to this to discover new markets without polling:

```solidity
event PoolCreated(
    uint256 indexed poolId,
    address indexed pool,
    address tokenX,
    address tokenY,
    bytes data
);
```

`poolId` is the index used by `getPoolAt`; `data` is the per-pool initialization blob (currently `maxValue (12 bytes) | oracle (20 bytes)`).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://developers.lfj.gg/poe/discovering-pools.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.
