# Get Pool Source: https://docs.hadron.fi/api-reference/get-pool GET https://api.hadron.fi/pools/{address} Returns detailed information for a single Hadron pool. ## Path Parameters The pool config PDA address. ## Query Parameters Solana cluster — `mainnet-beta` or `devnet`. ## Response Returns the same pool object shape as the [List Pools](/api-reference/list-pools) endpoint. ```json theme={null} { "address": "7ZRLTJBvJSy9VDyZmDoGW4b7noorCYnLUisyAXh7hxMz", "name": "SOL/USDC", "token_x": { "address": "So11111111111111111111111111111111111111112", "symbol": "SOL", "name": "SOL", "decimals": 9, "icon": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png" }, "token_y": { "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "symbol": "USDC", "name": "USDC", "decimals": 6, "icon": "" }, "token_x_amount": 5413038034, "token_y_amount": 515256215, "pool_config": { "authority": "Bk2qYNMa4hUkbutBcb4JHhMqAbGEFZq4KjicpMCwC2wn", "quoting_authority": "Bk2qYNMa4hUkbutBcb4JHhMqAbGEFZq4KjicpMCwC2wn", "oracle_mode": 0, "pool_state": "Initialized", "base_spread_bps": 5.0 }, "tvl": 990.81, "current_price": 87.85, "volume": { "24h": 364.16 }, "fees": { "24h": 0.59 } } ``` ## Errors | Status | Message | | - | - | | `404` | `Pool not found` | # List Pools Source: https://docs.hadron.fi/api-reference/list-pools GET https://api.hadron.fi/pools Returns a paginated list of all Hadron pools with token metadata, TVL, volume, and fees. ## Query Parameters All filters combine with logical **AND** and stack with `query` search and `cluster`. `total` and `pages` reflect the filtered result set. An unrecognized `pool_state` value simply returns zero matches. 1-based page number. Number of pools per page. Maximum `100`. Search by pool name, token symbol, mint address, or pool address (configPda). Filter to pools whose `authority` exactly matches this pubkey. Filter to pools whose `quoting_authority` exactly matches this pubkey. Filter to pools that include this mint address on **either** side (`token_x` or `token_y`). Filter to pools whose base token (`token_x`) mint matches this address. Filter to pools whose quote token (`token_y`) mint matches this address. Filter by pool state. Case-insensitive. One of `Uninitialized`, `Initialized`, `Paused`, `RejectSwaps`, `Closed`. Sort field and direction. Format: `field:direction`. **Fields:** `tvl`, `volume_24h`, `fees_24h` **Directions:** `asc`, `desc` Solana cluster — `mainnet-beta` or `devnet`. ## Response Total number of pools matching the query. Total number of pages. Current page number. Number of pools per page. Array of pool objects. Pool config PDA address. Pool display name (e.g. `SOL/USDC`). Base token metadata. Mint address. Token symbol. Token name. Token decimals. Token icon URL. Quote token metadata (same shape as `token_x`). Raw vault X balance (base token). Raw vault Y balance (quote token). Pool configuration. Pool authority pubkey. Quoting authority pubkey. Oracle mode (0 = default). Pool state — one of `Uninitialized`, `Initialized`, `Paused`, `RejectSwaps`, or `Closed`. Current base spread in basis points. Total value locked in USD. Current midprice (human-readable, e.g. `87.85` for SOL/USDC). 24-hour trading volume in USD. 24-hour fees collected in USD. ```json theme={null} { "total": 3, "pages": 1, "current_page": 1, "page_size": 20, "data": [ { "address": "7ZRLTJBvJSy9VDyZmDoGW4b7noorCYnLUisyAXh7hxMz", "name": "SOL/USDC", "token_x": { "address": "So11111111111111111111111111111111111111112", "symbol": "SOL", "name": "SOL", "decimals": 9, "icon": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png" }, "token_y": { "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "symbol": "USDC", "name": "USDC", "decimals": 6, "icon": "" }, "token_x_amount": 5413038034, "token_y_amount": 515256215, "pool_config": { "authority": "Bk2qYNMa4hUkbutBcb4JHhMqAbGEFZq4KjicpMCwC2wn", "quoting_authority": "Bk2qYNMa4hUkbutBcb4JHhMqAbGEFZq4KjicpMCwC2wn", "oracle_mode": 0, "pool_state": "Initialized", "base_spread_bps": 5.0 }, "tvl": 990.81, "current_price": 87.85, "volume": { "24h": 364.16 }, "fees": { "24h": 0.59 } } ] } ``` # Midprice History Source: https://docs.hadron.fi/api-reference/midprice-history GET https://api.hadron.fi/pools/{address}/midprice/history Returns sampled midprice history for a pool over a time range. ## Path Parameters The pool config PDA address. ## Query Parameters Sample interval. One of: `1m`, `5m`, `30m`, `1h`, `2h`, `4h`, `12h`, `24h`, `raw`. When set to `raw`, every recorded midprice point is returned without bucketing/sampling. Results are paginated via `cursor`. Start of the time range as a Unix timestamp in seconds (inclusive). Defaults to `end_time - 86400` (24 hours ago). End of the time range as a Unix timestamp in seconds (inclusive). Defaults to current time. Number of records per page (1–1000). Only applicable when `timeframe=raw`. Unix timestamp in seconds. Fetch records **before** this timestamp (newest first). Use the `next_cursor` value from a previous response to paginate backwards through history. Only applicable when `timeframe=raw`. Solana cluster — `mainnet-beta` or `devnet`. ## Response Start of the requested range (Unix seconds). End of the requested range (Unix seconds). The sample interval used. Timestamp of the oldest record in the current page (Unix seconds). Pass as `cursor` to fetch the next (older) page. `null` when there are no more records. Only present when `timeframe=raw`. Array of midprice samples. One entry per time bucket that contains data (sampled modes), or every recorded point (`raw` mode). Sample timestamp (Unix seconds). Solana slot number when this midprice update was confirmed on-chain. Raw midprice value. This is the on-chain Q32-decoded midprice representing `token_y per token_x` in raw units. To get a human-readable price, multiply by `10^(decimals_x - decimals_y)`. Base spread factor (Q32-decoded). A value near `1.0` means minimal spread. The spread in basis points is `(1 - base_spread_factor) * 10000`. Base58 transaction signature of the `UpdateMidprice` or `UpdateMidpriceAndSpreadFactor` instruction that produced this update. `null` for historical records ingested before signature tracking was added. ```json Sampled (1h) theme={null} { "start_time": 1773164464, "end_time": 1773250864, "timeframe": "1h", "data": [ { "timestamp": 1773164464, "slot": 410333466, "midprice": 0.08771598688326776, "base_spread_factor": 0.9994999999180436, "signature": "E6cGjfbdRs4ShbmZc1AHeLZg7vN79PYHFWe4..." }, { "timestamp": 1773168065, "slot": 410342211, "midprice": 0.08653769129887223, "base_spread_factor": 0.9994999999180436, "signature": "3Ni7GhiHoPmnUxcgpPMYW61qPkxUunj4WwB9..." } ] } ``` ```json Raw (paginated) theme={null} { "start_time": 1710000000, "end_time": 1710086400, "timeframe": "raw", "next_cursor": 1710003600, "data": [ { "timestamp": 1710000000, "slot": 409267135, "midprice": 145.23, "base_spread_factor": 0.9997, "signature": "44txvmp2QQJa9XLkG8Gj2zHnBScRkXxL5dHd..." }, { "timestamp": 1710000400, "slot": 409268012, "midprice": 145.45, "base_spread_factor": 0.9997, "signature": "5AUySbnZ8qjk1Zr7VqTW8tPKJ9Gm3CfWgJ7x..." }, { "timestamp": 1710003600, "slot": 409275890, "midprice": 145.12, "base_spread_factor": 0.9995, "signature": null } ] } ``` ## Errors | Status | Message | | - | - | | `400` | `Invalid timeframe` | | `400` | `start_time and end_time must be valid unix timestamps in seconds` | | `400` | `cursor must be a valid unix timestamp in seconds` | # API Overview Source: https://docs.hadron.fi/api-reference/overview REST API for accessing Hadron pool data, midprice history, volume, swaps, transactions, fees, and protocol metrics. ## Base URL ``` https://api.hadron.fi ``` ## Authentication Pass an optional API key via the `x-api-key` header to unlock higher rate limits. | Tier | Rate Limit | Identifier | | - | - | - | | No API key | 10 req/min | IP address | | With API key | Default 120 req/min | API key | Contact the Hadron team to request an API key for production integrations. # Pool Fees Source: https://docs.hadron.fi/api-reference/pool-fees GET https://api.hadron.fi/pools/{address}/fees Fees a pool captured over a time window — pool-captured spread and protocol fee, with the protocol fee broken down per fee-split recipient. Aggregates the fees a pool earned over the selected window into two parts: * **Pool-captured spread** — the spread the pool's curve earned (price curve, risk curve, base spread), excluding the protocol fee. * **Protocol fee** — the protocol fee captured, broken down per recipient for pools that route fees through the fee-split sidecar. Computed on-the-fly over the window's swaps. For very high-volume windows the response sets `truncated: true` (see the field below). ## Path Parameters The pool config PDA address. ## Query Parameters Lookback window ending now. One of `1h`, `24h`, `7d`, `30d`, or `all` (`all` aggregates the pool's full history). Solana cluster — `mainnet-beta` or `devnet`. ## Response The interval that was applied (echoes the request). Start of the window (Unix seconds). `0` when `interval=all`. End of the window (Unix seconds) — the request time. Pool's token X (base) mint. Pool's token Y (quote) mint. Aggregate fee totals over the window. Total swap volume over the window, quote-denominated. Pool-captured spread over the window (price/risk curve + base spread), quote-denominated. Excludes the protocol fee. Total protocol fee captured over the window, quote-denominated. Protocol fee collected in raw token-X atoms (from sells). Protocol fee collected in raw token-Y atoms (from buys). Number of swaps in the window. Per-recipient split of the protocol fee over the window. Empty (`[]`) for pools that use the default (single) fee recipient, for windows with no fee-bearing split swaps, or for windows entirely before per-swap split tracking began. The sum of recipients' `fee_usd` equals `totals.protocol_fee_usd` only when **every** fee-bearing swap in the window carried a split; it is less when the window also includes default-fee swaps or pre-tracking swaps. Recipient wallet address. Most recently observed split weight (parts-per-million) for this recipient in the window. Recipient's share of the protocol fee over the window, quote-denominated. Recipient's share in raw token-X atoms (from sells). Recipient's share in raw token-Y atoms (from buys). `true` if the per-query swap cap was reached, meaning the window contains more swaps than were aggregated. Narrow the `interval` for a complete result. ```json theme={null} { "interval": "7d", "start_time": 1772634648, "end_time": 1773239448, "mint_x": "So11111111111111111111111111111111111111112", "mint_y": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "totals": { "volume_usd": 184320.45, "spread_usd": 122.84, "protocol_fee_usd": 36.91, "protocol_fee_x_raw": 41230000, "protocol_fee_y_raw": 33110000, "swap_count": 612 }, "protocol_fee_split": [ { "recipient": "Rec1", "ppm": 700000, "fee_usd": 25.84, "fee_x_raw": 28861000, "fee_y_raw": 23177000 }, { "recipient": "Rec2", "ppm": 300000, "fee_usd": 11.07, "fee_x_raw": 12369000, "fee_y_raw": 9933000 } ], "truncated": false } ``` # Protocol Metrics Source: https://docs.hadron.fi/api-reference/protocol-metrics GET https://api.hadron.fi/stats/protocol_metrics Returns protocol-wide aggregate statistics across all Hadron pools. ## Query Parameters Solana cluster — `mainnet-beta` or `devnet`. ## Response Total value locked across all pools in USD. Total 24-hour trading volume across all pools in USD. Total 24-hour fees collected across all pools in USD. Total number of swaps in the last 24 hours. Total number of Hadron pools. ```json theme={null} { "total_tvl": 0, "volume_24h": 364.16, "fee_24h": 0.59, "swap_count_24h": 6, "total_pools": 3 } ``` # Recent Swaps Source: https://docs.hadron.fi/api-reference/recent-swaps GET https://api.hadron.fi/pools/{address}/swaps Returns swap events for a pool, ordered newest first. Cursor-paginated — you can walk the full history of a pool by following `next_cursor`. ## Path Parameters The pool config PDA address. ## Query Parameters Page size — number of swaps to return per request. Maximum `200`. Opaque pagination cursor. Omit on the first request; on subsequent requests, pass the `next_cursor` value from the previous response to fetch the next page. When the server returns `next_cursor: null` (equivalently `has_more: false`), you have reached the end of the pool's history. Solana cluster — `mainnet-beta` or `devnet`. Only return swaps whose **quote (Y) leg** is at least this many raw quote atoms. The quote leg is `input_amount` on a `buy` (Y to X) and `output_amount` on a `sell` (X to Y). For a USDC-quoted pool, `1000000` means "at least 1 USDC". Use this to keep dust trades out of a page. Only return swaps with `slot` strictly greater than this value. Made for polling: remember the highest `slot` you have processed and pass it back on the next call to receive just the swaps that landed since. `has_more: false` in the response means the walk reached the bound and nothing was left out. Only return swaps with `timestamp` strictly greater than this value, compared in whole seconds (the unit the response uses), so feeding back `data[0].timestamp` never repeats a swap. Accepts unix seconds (`1788659015`) or an ISO-8601 date-time (`2026-09-06T02:23:35Z`); a string without a zone designator is read as UTC. Numbers of `1e12` or more are treated as unix milliseconds. Two swaps landing in the same second as your bound are excluded together; when a gapless feed matters, prefer `after_slot`, which is exact. **How filtered pages are built.** `min_quote_amount`, `after_slot` and `after_timestamp` can be combined. The API walks the pool's history newest-first in blocks of 200 rows and keeps the rows that pass, until it has `limit` of them, reaches the `after_slot` or `after_timestamp` bound, or has scanned 1,000 rows. If the scan budget runs out, the page is returned with `has_more: true` and a `next_cursor` that resumes the walk, and it may hold fewer than `limit` rows (even none). Cursors from filtered requests look different from unfiltered ones; both are opaque, so always pass back exactly what you received. Following a filtered cursor never repeats or skips a swap, even when new swaps arrive in between. Polling recipe (every minute, ignoring anything under 5 USDC): ```bash theme={null} curl 'https://api.hadron.fi/pools/{address}/swaps?after_slot=LAST_SEEN_SLOT&min_quote_amount=5000000' \ --header 'x-api-key: YOUR_KEY' ``` Take `data[0].slot` from a non-empty response as the next `LAST_SEEN_SLOT`. ## Response Array of swap events on this page, ordered by most recent first. Solana transaction signature. Swap timestamp (Unix seconds). Solana slot number. Swap direction — `buy` (Y to X) or `sell` (X to Y). Raw input token amount. Raw output token amount. Input token mint address. Output token mint address. The pool midprice at the time of the swap (raw Q32-decoded value). Effective execution price in Y-per-X terms, excluding the protocol fee. Directly comparable to `midprice_at_swap`. The pool's base spread factor read from the oracle at the time of the swap. `1.0` means no base spread; e.g. `0.9995` means the LP charged ≈5 bps of base spread before any inventory skew. Values above `1.0` indicate the curve was skewed in the trader's favor (the LP gave up base spread to rebalance inventory) — this is the conceptual fee the LP is *still* earning even when `realized_spread_quote_raw` is negative. `null` for swaps recorded before this field was tracked. Vault X balance after the swap. Vault Y balance after the swap. Fee and execution quality metrics for the swap. Protocol fee in raw Y (quote-side) atoms. For sell swaps (fee paid in X), converted to Y-equivalent using midprice. Protocol fee in raw atoms of the **fee token** (the swap's input token — X on a sell, Y on a buy). Unlike `protocol_fee_quote_raw`, this is not midprice-converted. Mint of the fee token (equals `input_mint`). Spread captured by the pool in raw Y (quote-side) atoms. Positive values indicate pool profit; negative values indicate the trade executed better than midprice. For buy swaps this is a Y-equivalent conversion of the X atoms the pool saved. Spread captured by the pool in basis points of the trade's notional value at midprice. Unit-independent — directly comparable across pools and directions. Per-recipient breakdown of the protocol fee for pools whose fee routes through the **fee-split sidecar**. `null` for pools that use the default (single) fee recipient, and for swaps recorded before this field was tracked. Amounts are exact proportional shares of `protocol_fee_raw` (`protocol_fee_raw × ppm / Σ ppm`) — they sum to `protocol_fee_raw`. The split ratio is captured at the swap's slot, so it is exact even if the pool's recipient weights change later. Recipient wallet address. Recipient's split weight in parts-per-million, as configured on-chain at the time of the swap. The denominator is the sum of all recipients' `ppm` (not a fixed 1,000,000). Recipient's share of `protocol_fee_raw`, in fee-token atoms. Cursor to pass as `?cursor=...` on the next request to fetch the following page. `null` when there are no more swaps (end of history). `true` if more swaps are available beyond this page, `false` if this is the last page. ```json theme={null} { "data": [ { "signature": "5ZVLukBf3HfmT7d9Emte1fobjhtHsjps5TXtNZboTK3di76NbVUxHsLDFuzcnyhnjYLNnVdJajKg9k5NJCs9CLCi", "timestamp": 1773239448, "slot": 405713180, "direction": "buy", "input_amount": 86476334, "output_amount": 998378024, "input_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "output_mint": "So11111111111111111111111111111111111111112", "midprice_at_swap": 0.08647878072224557, "execution_price_at_swap": 0.08662, "base_spread_factor_at_swap": 0.9995, "vault_x_after": 5413038034, "vault_y_after": 515256215, "fees": { "protocol_fee_quote_raw": 0, "protocol_fee_raw": 0, "protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "realized_spread_quote_raw": 142136, "realized_spread_bps": 16.44, "protocol_fee_split": null } }, { "signature": "4b76z7T6gqn5aNjvDN3eE4X9dLrdR88DNYomkugjRvExxLRrYAgumaoGbzN8NYPFXvoXaeM9bbmD6P2tp5aTT2Tn", "timestamp": 1773239444, "slot": 405713171, "direction": "sell", "input_amount": 1000000000, "output_amount": 86347675, "input_mint": "So11111111111111111111111111111111111111112", "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "midprice_at_swap": 0.08649538387544453, "execution_price_at_swap": 0.08634768, "base_spread_factor_at_swap": 0.9995, "vault_x_after": 6411416058, "vault_y_after": 428792852, "fees": { "protocol_fee_quote_raw": 0, "protocol_fee_raw": 0, "protocol_fee_mint": "So11111111111111111111111111111111111111112", "realized_spread_quote_raw": 147709, "realized_spread_bps": 17.08, "protocol_fee_split": null } } ], "next_cursor": "eyJpZCI6ImozZDd4a203...", "has_more": true } ``` For a pool whose protocol fee routes through the fee-split sidecar, the `fees` object includes a populated `protocol_fee_split` (shares sum to `protocol_fee_raw`): ```json theme={null} "fees": { "protocol_fee_quote_raw": 12500, "protocol_fee_raw": 12500, "protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "realized_spread_quote_raw": 142136, "realized_spread_bps": 16.44, "protocol_fee_split": [ { "recipient": "Rec1", "ppm": 700000, "amount_raw": 8750 }, { "recipient": "Rec2", "ppm": 300000, "amount_raw": 3750 } ] } ``` # Recent Transactions Source: https://docs.hadron.fi/api-reference/recent-transactions GET https://api.hadron.fi/pools/{address}/transactions Returns Hadron and fee-split (sidecar) transactions for a pool, ordered newest first. Cursor-paginated — you can walk the full history of a pool by following `next_cursor`. ## Path Parameters The pool config PDA address. ## Query Parameters Page size — number of transactions to return per request. Maximum `200`. Opaque pagination cursor. Omit on the first request; on subsequent requests, pass the `next_cursor` value from the previous response to fetch the next page. When the server returns `next_cursor: null` (equivalently `has_more: false`), you have reached the end of the pool's history. Filter by instruction type (e.g. `SwapExactIn`, `Deposit`, `Distribute`). See the Instruction Types and Fee-Split Instruction Types tables below for possible values. When set, only transactions matching this type are returned. Pages may contain fewer than `limit` results. Solana cluster — `mainnet-beta` or `devnet`. ## Response Array of transaction records on this page, ordered by most recent first. Solana transaction signature. Transaction timestamp (Unix seconds). Solana slot number. Zero-based ordinal among the **Hadron** instructions in this transaction — not the absolute Solana instruction position. The first Hadron invocation is `0`, the second is `1`, and so on; non-Hadron instructions (compute budget, token transfers, other programs) are skipped when counting. Top-level Hadron instructions are counted before Hadron CPIs from inner instructions. A single Solana transaction can invoke the Hadron program multiple times (e.g. a router or batch); each invocation is recorded as its own row, disambiguated by `(signature, ix_index)`. Fee-split (sidecar) instructions in a transaction are recorded with a separate, higher `ix_index` range so they never collide with the Hadron rows of the same transaction (a fee-split call often CPIs into Hadron). The instruction that was executed — a Hadron instruction or a fee-split (sidecar) instruction. See the tables below for possible values. Whether the transaction succeeded. Error message if the transaction failed, `null` otherwise. Cursor to pass as `?cursor=...` on the next request to fetch the following page. `null` when there are no more transactions (end of history). `true` if more transactions are available beyond this page, `false` if this is the last page. ### Instruction Types | Type | Description | | - | - | | `Initialize` | Pool initialization | | `Deposit` | Liquidity deposit | | `Withdraw` | Liquidity withdrawal | | `SwapExactIn` | Swap with exact input amount | | `SetCurve` | Price curve update | | `UpdateMidprice` | Oracle midprice update | | `InitializeFeeConfig` | Global fee config initialization | | `UpdateFeeConfig` | Global fee config update | | `SetRiskCurve` | Risk curve update | | `UpdateBaseSpread` | Base spread factor update | | `UpdateMidpriceAndBaseSpread` | Combined midprice and spread update | | `SwitchPriceCurve` | Switch active price curve slot | | `SwitchRiskCurve` | Switch active risk curve slot | | `InitializeSpreadConfig` | Spread config initialization | | `UpdateSpreadConfig` | Spread config update | | `UpdateDeltaStaleness` | Delta staleness parameter update | | `NominateAuthority` | Nominate new pool authority | | `AcceptAuthority` | Authority transfer acceptance | | `SubmitCurveUpdates` | Batch curve update submission | | `ApplyCurveUpdates` | Apply pending curve updates | | `ClosePool` | Close and reclaim pool rent | | `SetPoolState` | Pool state change (pause/freeze/resume) | | `AllocateCurvePrefabs` | Allocate curve prefab storage | | `RotateFeeAdmin` | Rotate fee admin key | | `InitializePoolFeeConfig` | Per-pool fee config initialization | | `UpdatePoolFeeConfig` | Per-pool fee config update | | `SetAssetFee` | Set a per-asset-pair fee override on the global fee config | | `ValidateCurveUpdates` | Dry-run validation of queued curve updates | | `RemoveSpreadTriggers` | Remove specific spread triggers | | `UpdateDrawdownGuard` | Update drawdown guard threshold / rotation interval | | `UpdateFactorClamp` | Update the combined-factor clamp ceiling | | `ClosePoolFeeConfig` | Revert a pool from per-pool fee back to the global fee | | `RotateDepositAuthority` | Rotate the deposit authority | | `RotateWithdrawAuthority` | Rotate the withdraw authority | | `RotateQuotingAuthority` | Rotate the quoting authority (replaces `SetQuotingAuthority`) | | `RotateSpreadAdmin` | Rotate the spread config admin | | `RotatePauseAuthority` | Rotate the pause authority | ### Fee-Split Instruction Types Instructions from the fee-split sidecar program. They appear alongside Hadron instructions in this endpoint, attributed to the pool via the fee-split config's `hadron_pool_config`, and are filterable with `instruction_type`. Per-recipient credit and distribution amounts are not on these rows — those are tracked separately by the sidecar indexer. | Type | Description | | - | - | | `InitializeSplit` | Fee-split config created for the pool | | `UpdateCustomerDomain` | Recipient set / split-weight (ppm) update (the "update fee split" operation) | | `UpdateHadronSlot` | Hadron-slot (protocol recipient) update | | `Distribute` | Pending fees paid out to a recipient | | `Reinvest` | A recipient's pending fees reinvested into the pool | | `CloseSplit` | Fee-split config closed | ```json theme={null} { "data": [ { "signature": "3Qm9q3hP8oLpAaQ7s2y1Wb6kZ4uVnRceJ2hN1xVtQz8Kfw5rXdCgu7mEb9PtVZ2sYHn4aLrDk6oW3fJq1RcT5Bv", "timestamp": 1773239510, "slot": 405713340, "ix_index": 1000, "instruction_type": "Distribute", "success": true, "error": null }, { "signature": "XK7Cu5FSNkBP55ZMXLcMv1ZVUTB2cYCVrngtWHWf7ci8L3XjuVgnw1FwNQa7vsVNZ2QrHdwGVHkQqboLENp4Qj2", "timestamp": 1773239503, "slot": 405713326, "ix_index": 0, "instruction_type": "UpdateDeltaStaleness", "success": true, "error": null }, { "signature": "5ZVLukBf3HfmT7d9Emte1fobjhtHsjps5TXtNZboTK3di76NbVUxHsLDFuzcnyhnjYLNnVdJajKg9k5NJCs9CLCi", "timestamp": 1773239448, "slot": 405713180, "ix_index": 0, "instruction_type": "SwapExactIn", "success": true, "error": null } ], "next_cursor": "eyJpZCI6ImozZDd4a203...", "has_more": true } ``` # Volume History Source: https://docs.hadron.fi/api-reference/volume-history GET https://api.hadron.fi/pools/{address}/volume/history Returns historical trading volume for a pool in daily buckets. ## Path Parameters The pool config PDA address. ## Query Parameters Bucket size. Currently only `24h` is supported. Start of the time range as a Unix timestamp in seconds. Defaults to 7 days ago. End of the time range as a Unix timestamp in seconds. Defaults to current time. Solana cluster — `mainnet-beta` or `devnet`. ## Response Start of the requested range (Unix seconds). End of the requested range (Unix seconds). The bucket size used. Array of volume buckets aligned to UTC days. Bucket start timestamp (Unix seconds, UTC midnight). Trading volume in USD for this bucket. Fees collected in USD for this bucket. ```json theme={null} { "start_time": 1772646065, "end_time": 1773250865, "timeframe": "24h", "data": [ { "timestamp": 1772582400, "volume": 115.41, "fees": 0 }, { "timestamp": 1772668800, "volume": 1058.62, "fees": 0 }, { "timestamp": 1772755200, "volume": 267.98, "fees": 0 } ] } ``` Sub-day timeframes (`1h`, `4h`, `12h`) are planned for a future release. ## Errors | Status | Message | | - | - | | `400` | `Only 24h timeframe is supported for volume history in v1` | # Curves Source: https://docs.hadron.fi/concepts/curves ## Curves in Hadron At a high-level, curves allow makers to express **parameterized functions**. Curves determine the following: 1. **Price Curve**: *"I have defined a mid-price and base spread, but how do my quotes scale if a user tries to swap 1, 10, 100, 1000, 10000 SOL?"* 2. **Risk Curve**: *"I just received multiple orders within or across blocks, how do I automatically change my quotes now that my inventory is imbalanced?"* *Take a look at this amazing project put together by the Ghost Team, where you can see how different PropAMM quotes change as a function of volume. These graphs, in Hadron, can be thought of as Price Curves:* [*https://sandwiched.me/experiments*](https://sandwiched.me/experiments) ## Curve Types Each side of the market (bid and ask) has its own pricing curve. **These curves define how price changes as a function of input size**. They allow makers to express spread ladders, nonlinear depth, and asymmetric behavior between buying and selling. A curve is defined by a set of control points - example curve constructed [here](https://docs.hadron.fi/examples/bid-and-ask). Inventory curves apply an additional spread based on the pool’s current base/quote balance. They allow makers to: * Penalize trades that worsen imbalance * Incentivize trades that rebalance inventory * Express risk as a continuous function of inventory Importantly, inventory skew is applied without canceling or reposting orders, **enabling real-time risk adjustment and reducing intra-block pickoff**. # Points and Interpolations Source: https://docs.hadron.fi/concepts/interpolations ## Overview Points and interpolations are the means by which you define curves. ## Defining Curves Each bid or ask curve consists of **control points**. Every point specifies: * **Input Amount:** Trade size in atoms * **Price Factor:** Adjustment relative to mid-price - equivalent to spread * **Interpolation Mode:** How pricing transitions to the next point Points define the shape of the curve; interpolation determines the behavior between them. ## Interpolation Modes Hadron supports multiple interpolation types, which can be mixed across points: * **Step** (0): Constant price factor between point A → B. * **Linear** (1): Linearly interpolates price between points. * **Marginal Step** (2): Points store average spread, producing constant marginal pricing between A → B. Gives orderbook-like behavior where each size tier has a flat marginal price. * **Hyperbolic** (3): Rational easing with shape parameter `k` .
`k=1.0` is exactly linear, `k<1.0` is concave (saturating), `k>1.0` is convex (accelerating). * **Quadratic** (4): Quadratic easing with shape parameter `k`. Formula: `ease(t) = t + k*(t² - t)`. `k=0` is linear, `k>0` is convex (stays near f0 longer), `k<0` is concave (moves toward f1 quickly). * **Cubic** (5): Cubic easing with 2 shape parameters `a` and `b`. Formula: `ease(t) = t + a*(t² - t) + b*(t³ - t)`. `a=0,b=0` is linear. Allows S-curves and richer shapes. By combining points and interpolation types, makers can construct virtually any curve shape — from order-book ladders to smooth nonlinear depths. # Mid-price And Base Spread Source: https://docs.hadron.fi/concepts/mid-price ## Hadron Curves Are Anchored Around Midprice Mid-price and base-spread are initialized and updated by the maker, and anchor the entire swap function. The instruction to update these parameters sit \< 40 CUs. **Importantly**, mid-price must be *actively* managed, by the maker, sending updates to make sure price has not gone stale. # Toxic Flow Prevention Source: https://docs.hadron.fi/concepts/toxic-flow-prevention ### Segmenting Toxic Flow With Hadron Hadron is designed to give operators granular control over toxic flow. Hadron allows users to monitor for various accounts in instructions and control quoting logic during runtime. **How it works:** On Solana, the SVM requires all accounts touched in a transaction to be passed into the instructions for safety. Hadron let’s operators apply conditions that affect the quoting logic based on the accounts passed into the transaction at runtime. * Operators decide which accounts are affected and the quoting behavior for those accounts * Example: Add 3Bps spreads to swaps not from whitelisted routers * Example: Reduce spreads for swaps with a phantom or fomo fee wallet * Example: Blacklist known arbitrage wallet and prevent trades from this wallet # Core Design Source: https://docs.hadron.fi/core-design Designed For Modularity ## **Generalizable** Instead of hard-coding a single formula, Hadron treats pricing as an explicit, updatable function defined by the maker. ***This means that makers can iterate on their entire pricing logic without needing to update the underlying contract.*** ### Functionality As a baseline, all Hadron pools (PropAMM instances) are composed of the following: * **Mid-price**: Price anchor for all swaps * **Base Spread**: Static spread applied per side * **Bid/Ask Curve**: Customizeble curves that define quoting logic as a function of input atoms * **Inventory curve**: Customizable curves that express risk as a function of inventory imbalance ### Isolated Liquidity The maker that creates the pool is the sole authority of that pool. They are the only party that can control the pool, including withdrawing, depositing, and updating quoting logic. ### Toxic-Flow Management Each maker can define wallets or programs that pool should not interact with. For instance, you can widen or tighten spread for (Jito, OKX, a specific wallet, etc.). # Update Oracle and Curves Source: https://docs.hadron.fi/examples/bid-and-ask ## **Defining mid-price** Defining and updating mid-price on Hadron has three variables * **Input:** Mid-price is defined in **quote atoms per base atom** * **Sequence:** Sequence is a nonce sent by the operator to prevent stale quotes from block builders re-ordering transactions. Instructions with a sequence strictly less than the current sequence will be fail. * **Base spread (optional):** Operators can initialize an optional base spread with the mid-price update. ```typescript theme={null} // `pool` is a loaded Hadron instance; `authority` is the pool authority (see SDK ▸ Quickstart) // Updating a midprice of 117.20 SOL/USDC and a base spread of 5 bps const ix = pool.updateMidpriceAndBaseSpread(authority, { // midprice = quote atoms per base atom (USDC 6 decimals, SOL 9 decimals) midpriceQ32: toQ32(117.20 * 1e6 / 1e9), // $117.20 SOL/USDC spreadFactorQ32: spreadBpsToQ32(5), // 5 bps base spread sequence: 1n, // strictly-increasing nonce }); ``` ## Building Bid and Ask Curves **Simple 3 point curve** Points on Hadron are a function of 3 input values: * **Volume**: Input volume in atoms * **Spread**: Distance from the Mid-price * **Interpolation mode**: Moving between any two points ```typescript theme={null} // 3 point bid curve with a midprice of 1.00 // Points: Input Amount 0 (base), 1000, 2000 units // Spread of 10, 20, 50 Bps from Mid // Interpolating step wise for all 3 points const ix = pool.setCurve(authority, { side: Side.Bid, defaultInterpolation: Interpolation.Step, points: [ { amountIn: 0n, priceFactor: 0.9990 }, // 0-1000: 10bps fee { amountIn: 1000n, priceFactor: 0.9980 }, // 1000-5000: 20bps fee { amountIn: 5000n, priceFactor: 0.9950 }, // 5000+: 50bps fee ], }); ``` ### Curve Visualization: Bid Ask # HumidiFi Source: https://docs.hadron.fi/examples/humidifi Rebuilding HumidiFi's Curve With Hadron **HumidiFi:** HumidiFi is the largest propAMM on Solana, with over \$50bn in 90day volume. Image (18) *Source: Bid/Ask curve plotted from running the HumidiFi binaries in liteSVM. Note that HumidiFi curves follow this general shape, widening, shrinking, and shifting every slot.* For simplicity, we will linearly approximate humidifi's curve with just a few knots, although you can get even closer with more data points or hyperbolic interpolation.\ \ Under the hood, Humidifi is approximating log decay with very small linear segments. HumidiFi Bid/Ask Curve: | **amount\_in\_sol** | **average\_price\_usdc\_per\_sol** | | :- | :- | | 1 | 101.11448 | | 491.12256128 | 101.109647509533 | | 493.12306153 | 101.10963548795 | | 4000 | 101.08382844375 | | **amount\_in\_sol** | **average\_price\_usdc\_per\_sol** | | :- | :- | | 1.0 | 101.135357068354 | | 491.122561279057 | 101.141372888682 | | 493.123061523928 | 101.141398399866 | | 4000.0 | 101.172231918849 | Creating this curve with Hadron: ```typescript theme={null} // `pool` is a loaded Hadron instance; `authority` is the pool authority (see SDK ▸ Quickstart) // creating a 4 point bid/ask curve with hadron with midprice of 101.125 const bidCurveIx = pool.setCurve(authority, { side: Side.Bid, defaultInterpolation: Interpolation.Linear, points: [ { amountIn: 1n, priceFactor: 0.99989678, interpolation: Interpolation.Step }, { amountIn: 491n, priceFactor: 0.99984899, interpolation: Interpolation.Linear }, { amountIn: 493n, priceFactor: 0.99984887, interpolation: Interpolation.Linear }, { amountIn: 4000n, priceFactor: 0.99959367, interpolation: Interpolation.Step }, ], }); const askCurveIx = pool.setCurve(authority, { side: Side.Ask, defaultInterpolation: Interpolation.Linear, points: [ { amountIn: 1n, priceFactor: 1.00010322, interpolation: Interpolation.Step }, { amountIn: 491n, priceFactor: 1.00016271, interpolation: Interpolation.Linear }, { amountIn: 493n, priceFactor: 1.00016297, interpolation: Interpolation.Linear }, { amountIn: 4000n, priceFactor: 1.00046787, interpolation: Interpolation.Step }, ], }); ``` *Note: This is a simple linear based approximation of the curve, however the Hadron quadratic and other non linear interpolation leads to a smoother replica of the HumidiFi curve* # Mixed Interpolation Source: https://docs.hadron.fi/examples/mixed-interpolation Points can be connected with any interpolation method, allowing you to create nearly any quoting function. In this example, we will look at a mixed interpolation curve. Here, we define a curve with "step" and "linear". ```typescript theme={null} // `pool` is a loaded Hadron instance; `authority` is the pool authority (see SDK ▸ Quickstart) // 5 point ask curve with a midprice of 1.00 // Points: Input Amount 0 (base), 1000, 2000, 5000, 10000 units // Spread of 10, 20, 50, 100, 150 Bps from Mid // Mixed Interpolation across points const askCurveIx = pool.setCurve(authority, { side: Side.Ask, defaultInterpolation: Interpolation.Linear, points: [ { amountIn: 0n, priceFactor: 1.0010, interpolation: Interpolation.Step }, // 10bps { amountIn: 1000n, priceFactor: 1.0020, interpolation: Interpolation.Linear }, // 20bps { amountIn: 2000n, priceFactor: 1.0050, interpolation: Interpolation.Linear }, // 50bps { amountIn: 5000n, priceFactor: 1.0100, interpolation: Interpolation.Step }, // 100bps { amountIn: 10000n, priceFactor: 1.0150, interpolation: Interpolation.Step }, // 150bps ], }); ``` ## Curve Visualization: Mixed Interpolation *This is a mixed curve with no inventory skew logic* # Integrating as an Order Book Source: https://docs.hadron.fi/examples/order-book Hadron is fully reducible to an order book, with one key difference. ## Why traditional spot order books have failed on-chain 1. **You can't update your full book atomically**: on a CEX, you batch-cancel and batch-place orders. On Solana, transaction size limits cap how many orders you can place at once. Refreshing a book takes multiple transactions, and between them, your quotes are partially stale. Searchers often see this and pick you off. 2. **Block latency**: from the moment you submit a cancel until it confirms, your resting order is live. On Solana it's at least one block (\~400ms), and block priority favors low-CU transactions, so a searcher's single-instruction pickoff lands higher in the block than your multi-instruction cancel/replace. On-chain order books have fundamentally been designed for takers. For example, a batch update on Manifest (a large Solana-native orderbook) costs \~50,000 CUs. Even if that txn lands in the same block as a price move, a searcher's low-CU pick-off txn gets scheduled higher in the block, so your refresh arrives after. ## Hadron Unlike traditional on-chain order books, with Hadron you can efficiently place/cancel orders and segment flow, preventing pick-off. Instead of placing individual orders that each cost CUs to create, modify, and cancel, you define a **continuous function** that maps any incoming trade to a price. **Refreshing your entire book (curve) is a single mid-price update: \~32 CUs.** That's 1,500× cheaper than a Manifest batch update, 3,000× cheaper than adding/removing concentrated liquidity in an AMM, and you land near the top of the block for a structural maker advantage. ### How does this work, I thought Hadron was a PropAM? Every Hadron pool is defined by a single function: ``` output = f(input_size, mid_price, price_curve, inventory_curve) ``` where `price_curve` and `inventory_curve` are parameterized functions of "points" and "interpolations." To quote as an Order Book, we use **only** the inventory curve, with `step`-interpolated points. When a swap arrives, Hadron walks through the inventory curve like an order book, applying different spreads to the mid-price at each level. **Key advantage:** because all prices are defined as **spreads relative to mid-price**, a single mid-price update (\~32 CUs) instantly shifts every level in the book. That is equivalent to cancelling and re-placing your entire ladder of limit orders in one atomic operation. In the example below, change the mid-price to see the entire book shift, then increase "Trade size" to watch orders get filled: