The hooks a user can select
Every hook putty ships, one row per Solidity file in `packages/contracts/src/hooks/`. Each row carries what the hook **does** (written from the contract's own NatSpec), what a deployment **needs** (the constructor arguments and the capabilities it cannot work without), the Uniswap v4 **permission bits** its address must end in, and its **audit status**. **Every row is `experimental`, and a client must render that as "not audited".** These seven contracts are hand-written in this repo and none has been through an external audit. The label is the contracts module's own `CONTRACT_AUDIT_LABELS` vocabulary (`audited` / `reviewed` / `experimental`) so a preset and a hook cannot be described in two different sets of words. Do not collapse `experimental` into a tick. **`hookFlags` is a number a deployer needs before deploying.** A Uniswap v4 hook's low 14 address bits ARE its permission manifest, and a CREATE2 deploy must be MINED to an address ending in those bits or the pool refuses the hook. Each value is transcribed from that contract's own `getHookPermissions()` body, and it is checked at load against the miner. **`source` is a path into `packages/contracts`.** The description is a summary putty wrote; the contract is the thing the user is about to trust with real funds. **This list is asserted against the directory it describes.** The suite fails if a file is added to or removed from `packages/contracts/src/hooks/` without a row here, or if a row names a file that does not exist. A catalog entry nobody can select — or a shipped hook nobody can find — is the same dead surface as an unregistered tool, and it does not ship.
Every hook putty ships, one row per Solidity file in packages/contracts/src/hooks/. Each row carries what the hook does (written from the contract's own NatSpec), what a deployment needs (the constructor arguments and the capabilities it cannot work without), the Uniswap v4 permission bits its address must end in, and its audit status. Every row is experimental, and a client must render that as "not audited". These seven contracts are hand-written in this repo and none has been through an external audit. The label is the contracts module's own CONTRACT_AUDIT_LABELS vocabulary (audited / reviewed / experimental) so a preset and a hook cannot be described in two different sets of words. Do not collapse experimental into a tick. hookFlags is a number a deployer needs before deploying. A Uniswap v4 hook's low 14 address bits ARE its permission manifest, and a CREATE2 deploy must be MINED to an address ending in those bits or the pool refuses the hook. Each value is transcribed from that contract's own getHookPermissions() body, and it is checked at load against the miner. source is a path into packages/contracts. The description is a summary putty wrote; the contract is the thing the user is about to trust with real funds. This list is asserted against the directory it describes. The suite fails if a file is added to or removed from packages/contracts/src/hooks/ without a row here, or if a row names a file that does not exist. A catalog entry nobody can select — or a shipped hook nobody can find — is the same dead surface as an unregistered tool, and it does not ship.
Response Body
application/json
application/json
curl -X GET "https://example.com/hook-catalog"{ "hooks": [ { "id": "string", "title": "string", "description": "string", "hookFlags": "string", "permissions": [ { "flag": "BEFORE_INITIALIZE_FLAG", "canTouch": [ "string" ] } ], "requiredCapabilities": [ "string" ], "auditStatus": "audited", "source": "string" } ], "count": 0, "auditStatuses": [ "audited" ]}Scan a token before you buy it GET
The free-layer Scan from §3.7: what a trader is being scammed by, for one token on one chain. It answers, from the chain itself: - **Supply and mint.** `totalSupply()` raw, and whether the owner can mint more. A live mint function held by an EOA is the flag; a pausable one is worse still, and is reported separately. - **LP lock.** Whether the pool's liquidity can be withdrawn, and until when. - **Fee parameters.** The pool's LP fee and, for a putty pool, the putty fee in bps. - **Holder concentration.** The top wallets by recent `Transfer` movement, and whether they hold more than the served concentration threshold. - **The putty Verify label**, attached from `runVerify` rather than reimplemented. **Public, unauthenticated, and free.** No bearer token is required and none is charged; this is the acquisition surface from §3.7, and a security report behind a login is a report almost nobody reads. The same split `POST /verify` makes. **Every field is measured, not-measurable, or failed — and the three are different.** Each measured field is a `{ status, value }` or a `{ status, kind, reason }` union. A read that failed is `unavailable` with `kind: "read_failed"` and the node's own words; a thing this data source cannot answer is `unavailable` with `kind: "not_measurable"` and a reason naming the seam that could. **Neither is ever rendered as `0`, `[]`, or a null with no reason** — a failed holder census must not read as "zero holders", which is the bug class this endpoint exists to stop repeating. So: `holders` is `null` on a single node (counting every holder means walking an indexed log from genesis) while the `topHolders` window beside it is real; the LP lock is `not_measurable` rather than `unlocked` when putty has no index of lockers; and the simulated buy/sell is `not_measurable` because a token address alone cannot price a swap. **Amounts are decimal strings end to end.** A 1e9 supply at 18 decimals is thirty digits and a double cannot hold it, so `totalSupplyRaw`, every `balanceRaw`, and every percentage are strings. Do not parse them into a number to display a total. **`clearedForMainnet` is always `false`** and is declared as the literal `false` in the schema so the document states what the code enforces: no putty report, of any label, is an external audit. A `verified custom` label means every check ran and passed on the evidence putty had — read `verifyLabelExplanation` for the sentence that must be shown beside it.
Draft a hook deployment to sign POST
Validates `params` against the hook's real constructor and returns the **unsigned** deployment: the constructor arguments ABI-encoded, the address suffix the deploy must land on, and the hook's audit status. **Nothing is deployed and nothing is signed.** There is no key in this module and no broadcast call in it. The caller signs the transaction through the B0 signing path and putty never holds the signer, which is the same split the Launch Kit keeps. **Nothing is defaulted into existence.** A parameter the hook does not take is a **400** naming the names it does take; a required one that is missing is a **400** naming it; a value that is not the right shape for its declared type is a **400** naming the shape. Every argument arrives as a string and is encoded as the Solidity type the constructor declares — a `uint24` sent as a JSON `number` has already lost precision on the wire. A `hookId` that is not in the catalog is a **404** that lists the ids that are. It is never a default and never a 400, because a caller who asked for a hook that does not exist and got one that does would sign a transaction for something they did not choose. **`expectedAddress` is `null` until a CREATE2 salt has been mined** for these exact constructor arguments on this chain. Mining is a search, not a calculation, and a client must show "not mined yet" rather than a guessed or zero address. The treasury parameter goes through the same `assertTreasurySafe` guard the pool and launch paths use, so a fee cannot be pointed at the zero address — a transaction that is valid onchain and silently wrong.