Skip to content

Pool API

The Pool API lists every Uniswap v4 pool initialized on Robinhood Chain and reads live state straight from the PoolManager via StateView.

Endpoint What it does
GET /v1/pools Indexed pools, newest first
GET /v1/pools/:poolId Live state by PoolId
POST /v1/pools/state Live state by pool key
POST /v1/pools/id PoolId for a pool key (pure, no chain call)
GET /v1/stats Index totals and v4 contract addresses

A v4 pool is identified by its key:

Field Notes
currency0, currency1 Token addresses, sorted ascending. Native ETH is 0x0000000000000000000000000000000000000000
fee LP fee in hundredths of a bip (500 = 0.05%, 3000 = 0.30%), or 8388608 (0x800000) for a dynamic-fee pool
tickSpacing 1 to 32767
hooks Hook address, or the zero address for none

The PoolId is keccak256(abi.encode(key)). HookKit accepts currencies in either order and sorts them for you.

Terminal window
curl -X POST https://api.hookkit.dev/v1/pools/id \
-H "content-type: application/json" \
-d '{
"currency0": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"currency1": "0x0000000000000000000000000000000000000000",
"fee": 500,
"tickSpacing": 10
}'
{
"poolId": "0x387bf619da4d3fb62bb276482693dba1b9b3520f573cabdfe033384a24125982",
"key": {
"currency0": "0x0000000000000000000000000000000000000000",
"currency1": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"fee": 500,
"tickSpacing": 10,
"hooks": "0x0000000000000000000000000000000000000000"
},
"sorted": true
}

sorted: true means the currencies you passed were swapped into canonical order.

Terminal window
curl "https://api.hookkit.dev/v1/pools?hooked=true&limit=2"
Param Notes
hook Only pools using this hook
token Only pools containing this token (either side)
hooked true for pools with a hook, false for pools without
limit 1 to 100, default 25
offset Default 0
{
"total": 103805,
"pools": [
{
"poolId": "0x641df1e1715c14a6ed27188b42f1b0ac0cc58dc8ce86ca18fd1810addb97eddc",
"key": {
"currency0": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
"currency1": "0xe8C701e699e6027654A5634732EC67914BD13Ba3",
"fee": 8388608,
"tickSpacing": 200,
"hooks": "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544"
},
"pair": "WETH/?",
"currency0": { "address": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73", "symbol": "WETH", "decimals": 18 },
"currency1": { "address": "0xe8C701e699e6027654A5634732EC67914BD13Ba3", "symbol": null, "decimals": null },
"hooked": true,
"dynamicFee": true,
"createdBlock": 29508840,
"createdAt": "2026-08-06T16:55:59.000Z",
"txHash": "0x8fcadfefee6ecc0ead8a6f072f15fd72ce1c07221bb6bdcdc1f14067721e4050"
}
],
"limit": 2,
"offset": 0
}

List results carry token metadata from the index; symbol and decimals are null for tokens HookKit has not read yet. The live state endpoints below always read metadata onchain.

Terminal window
curl https://api.hookkit.dev/v1/pools/0x641df1e1715c14a6ed27188b42f1b0ac0cc58dc8ce86ca18fd1810addb97eddc
{
"poolId": "0x641df1e1715c14a6ed27188b42f1b0ac0cc58dc8ce86ca18fd1810addb97eddc",
"key": {
"currency0": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
"currency1": "0xe8C701e699e6027654A5634732EC67914BD13Ba3",
"fee": 8388608,
"tickSpacing": 200,
"hooks": "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544"
},
"currency0": { "address": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73", "symbol": "WETH", "name": "WETH", "decimals": 18 },
"currency1": { "address": "0xe8C701e699e6027654A5634732EC67914BD13Ba3", "symbol": "LARP", "name": "Live Action Roleplay", "decimals": 18 },
"dynamicFee": true,
"hooked": true,
"state": {
"initialized": true,
"sqrtPriceX96": "10872425402858764347486285145759394",
"tick": 236600,
"liquidity": "0",
"lpFee": 7000,
"lpFeePercent": 0.7,
"protocolFee": 0
},
"price": { "WETH/LARP": 18831881196.75212, "LARP/WETH": 5.310143949784831e-11 },
"hook": {
"address": "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544",
"enabled": ["beforeInitialize", "afterAddLiquidity", "afterRemoveLiquidity", "afterSwap", "afterSwapReturnDelta"],
"capabilities": [
{ "level": "warning", "flag": "afterSwapReturnDelta", "note": "Can charge or rebate tokens after each swap, e.g. a hook fee on top of the LP fee." },
{ "level": "info", "flag": "afterSwap", "note": "Runs after every swap: oracles, points, limit orders, rebalancing." },
{ "level": "info", "flag": "initialize", "note": "Runs when a pool is created with this hook (can restrict which pools use it)." }
]
},
"created": {
"block": 29508840,
"txHash": "0x8fcadfefee6ecc0ead8a6f072f15fd72ce1c07221bb6bdcdc1f14067721e4050",
"at": "2026-08-06T16:55:59.000Z"
}
}
Field Meaning
state.sqrtPriceX96, state.tick Current price as Q64.96 and tick
state.liquidity In-range liquidity. 0 does not always mean “no trades”: hooks with beforeSwapReturnDelta or launchpad-style accounting can still fill swaps
state.lpFee Current LP fee in hundredths of a bip. For dynamic-fee pools this is the fee the hook last set
state.protocolFee Packed protocol fee for both directions
price Spot price both ways, adjusted for decimals
hook Decoded permissions and capability notes, or null
created Initialize block and tx from the index, or null when looked up by key and not indexed

GET /v1/pools/:poolId needs the pool to be in the HookKit index (to recover its key). For any pool, indexed or not, pass the key instead:

Terminal window
curl -X POST https://api.hookkit.dev/v1/pools/state \
-H "content-type: application/json" \
-d '{
"currency0": "0x0000000000000000000000000000000000000000",
"currency1": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"fee": 500,
"tickSpacing": 10,
"hooks": "0x0000000000000000000000000000000000000000"
}'

A pool that is not in the index returns 404 not_found with a message asking for the key; an uninitialized key returns 404 not_found as well.

Terminal window
curl https://api.hookkit.dev/v1/stats
{
"chain": {
"id": 4663,
"name": "Robinhood Chain",
"explorer": "https://robinhoodchain.blockscout.com",
"contracts": {
"poolManager": "0x8366a39cc670b4001a1121b8f6a443a643e40951",
"positionManager": "0x58daec3116aae6d93017baaea7749052e8a04fa7",
"stateView": "0xf3334192d15450cdd385c8b70e03f9a6bd9e673b",
"quoter": "0x8dc178efb8111bb0973dd9d722ebeff267c98f94",
"universalRouter": "0x204FAca1764B154221e35c0d20aBb3c525710498",
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
}
},
"index": {
"pools": 288928,
"hookedPools": 103805,
"uniqueHooks": 4115,
"tokens": 10557,
"indexedThroughBlock": 29509069,
"headBlock": 100855225
}
}

The index follows PoolManager Initialize events from the PoolManager’s deployment block. Compare indexedThroughBlock with headBlock to see how far behind the chain head it is; pools created after indexedThroughBlock are not listed yet but can always be read by key.

import { HookKit } from "@hookkit/sdk"
const hookkit = new HookKit()
const { pools } = await hookkit.pools.list({ hook: "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544", limit: 10 })
const { poolId } = await hookkit.pools.id({
currency0: "0x0000000000000000000000000000000000000000",
currency1: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
fee: 500,
tickSpacing: 10,
})
const byId = await hookkit.pools.get({ poolId })
const byKey = await hookkit.pools.get({
currency0: "0x0000000000000000000000000000000000000000",
currency1: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
fee: 500,
tickSpacing: 10,
})
const stats = await hookkit.stats()