Docs

Developers

Route through Socket

For routers and aggregators. One integration reaches every Socket pool, whatever hook it has, as long as you read the hook's accounts from the pool and simulate.

Every Socket pool has the same program, the same swap instruction and the same fixed accounts. Hook-specific accounts come from a list stored with the pool, so a router needs no code per hook. What it does need is a policy for which hooks it trusts.

The integration#

  1. Discover pools

    Read all pool accounts of the Socket program (8,192 bytes, tag SOCKPOOL), or page through GET /pools on a Socket API. Decode with the SDK's decodePool, which checks the owner, size, tag, version and parameters, then call validatePoolAddress to check the account sits at the address its creator and nonce derive.

  2. Check the hook

    A pool with the System Program as its hook has no hook. Otherwise, route only if the hook program is on your allowlist. A pool's hook address never changes, but an upgradeable hook program's code can, so review the upgrade authority too.

  3. Resolve the hook's accounts

    Read the hook account list at ["extra-account-metas", pool]. It lists up to eight accounts, each with its expected owner and write access. Fetch them and check that each exists with that owner. Append them to the swap in the listed order.

  4. Quote

    Run the swap through the SDK's math port with the pool's state and ticks, or call POST /quote/swap. For the built-in hooks, the SDK also reproduces the dynamic fee (dynamicFeeAt) and the range-order guard (rangeOrderAfterSwap). An external hook's fee and behavior can't be predicted from state; quote it at the base fee and let simulation decide.

  5. Build and simulate

    Build the swap with swapInstruction, set a compute limit, and simulate. A failed simulation is a clean answer: the pool can't take this trade right now. Route elsewhere.

Swap accounts#

#AccountWritableSigner
0Swapper✓
1Pool✓
2Swapper's token A account✓
3Swapper's token B account✓
4Vault A✓
5Vault B✓
6SPL Token program
7Hook account list
8Hook program (System Program if none)
9Hook authority
10+The hook's extra accounts, as listedas listed

No tick arrays, no oracle accounts, no per-hook additions beyond the list. A pool with a built-in hook adds exactly one account, its hook state.

Swap arguments#

FieldTypeMeaning
amountu64Input for exact-in, output for exact-out.
limitu128Square-root price limit, strictly on the swap's side of the current price. The SDK turns 0 into the domain end.
a_to_bboolSell A for B (price falls) or B for A (price rises).
exact_inboolWhich side amount fixes.
thresholdu64Exact-in: minimum output. Exact-out: maximum input including any surcharge.
max_total_inputu64An explicit cap on CLMM input plus surcharge.

Hooks a router should know#

HookWhat can differ from a plain pool
No hookNothing.
No-opCompute only.
Dynamic feeThe fee rises after price moves and decays per second. Reproducible from hook state with dynamicFeeAt.
TWAP oracleCompute only. The fee is the base fee.
Range orderLiquidity is one owner's order. After a fill, swaps back into the range revert until the owner withdraws. Check with rangeOrderAfterSwap or the quote's blocked field.
ExternalAnything within the pool's bounds: a fee up to the max fee, a surcharge up to the cap, refusals. Allowlist and simulate.

Compute#

A swap's compute depends on the ticks it crosses and the hook's calls. Measured costs for this build are on the No-op page. Each pool's hook_budget bounds what one hook call may use, but it can't reserve compute: set the transaction's compute limit from simulation, with headroom. Transactions prepared by the Socket API set a limit of 1,000,000 units unless the request asks for another value between 10,000 and 1,400,000.

Multi-hop#

Each Socket pool has its own vaults, so a route through two Socket pools is two swap instructions, each settling separately. Both can sit in one transaction; if either fails, both revert.