Build the hook once. Route it everywhere.
Support hooked tokens with a few calls, or make your own hook routable by publishing a manifest.
Quickstart
Wallets and apps can make a hooked transfer safe and explainable in four lines.
npm i @hookway/sdk @solana/web3.js
import { Connection } from "@solana/web3.js";
import { Hookway } from "@hookway/sdk";
const hw = new Hookway({ connection: new Connection(RPC_URL) });
const sim = await hw.simulateTransfer({ mint, from: owner, to: recipient, amount: 1_000n });
if (!sim.ok) return showError(hw.explainFailure(sim).reason); // plain English, never a guess
const tx = await hw.buildTransfer(sim); // unsigned VersionedTransaction
await wallet.signAndSendTransaction(tx);SDK reference
@hookway/sdk talks to the chain directly through your RPC for inspection, resolution and simulation, and to the HOOKWAY API for routes. It fails closed: anything it cannot verify returns an error, not a default.
inspectToken(mint)Mint, program, Token-2022 extensions, transfer-hook program, upgrade authority, validation PDA, manifest, risk labels.inspectHook(programId)Program account + ProgramData: upgradeable?, authority, last deploy slot, registry entry, manifest.resolveAccounts({ mint, source, destination, owner, amount })Reads the ExtraAccountMetaList PDA and resolves every extra account (seeds, account data, instruction data).simulateTransfer({ mint, from, to, amount })Builds the transfer, runs simulateTransaction, returns a SimulationResult with trace, CU and structured errors.explainFailure(error, hook?)Maps program error codes to plain English via the hook manifest; says “unknown” rather than guessing.buildTransfer(simulation | params)Returns an unsigned VersionedTransaction (compute budget + ATA + TransferChecked + hook accounts).getCompatibleRoutes({ inputMint, outputMint, amount })Asks the HOOKWAY API for simulated, ranked routes; never returns an unsimulated route as valid.
Hook Manifest v0.1
Draft · HOOKWAY proposalA typed description of what your hook needs and enforces: program, version, authority, config schema, account requirements, compatibility, transaction requirements, simulation adapter, human-readable error explanations and known restrictions. It is a proposal, not an adopted standard. The on-chain ExtraAccountMetaList stays the source of truth for accounts — HOOKWAY cross-checks every manifest against it and against the program's real upgrade authority.
Must match the mint’s TransferHook extension and the program’s ProgramData. Mismatch ⇒ fail closed.
Seeds mirror spl-tlv-account-resolution: literal, account index, instruction-data slice. external ⇒ unsupported.
Whether plain transfers work, which venues are allowed, max extra accounts.
How wallets turn your custom error into a sentence. Templates may use config keys.
Manifest checker
Edit the example (HOOKWAY Max Wallet 1.2.0) and watch validation update.
- ✓ Schema valid (manifest v0.1)
- ✓ All accounts derivable without off-chain input
Shape-only check in the browser. The registry additionally cross-checks program ID, upgrade authority and the on-chain ExtraAccountMetaList (POST /api/v1/manifests/check).
HTTP API
JSON over HTTPS. Same data and simulation engine as the app. Errors are structured: { ok: false, error: { code, message } }.
- GET/api/v1/healthLiveness + data mode
- GET/api/v1/hooksRegistry list (?risk=, ?kind=)
- GET/api/v1/hooks/{slug}Hook object
- GET/api/v1/hooks/{slug}/manifestManifest v0.1 JSON
- GET/api/v1/tokensToken index (?hook=, ?risk=, ?q=)
- GET/api/v1/tokens/{mint}/inspectToken report (?source=chain in live mode)
- POST/api/v1/simulate{ mint, direction, amount, venue }
- POST/api/v1/routes{ inputMint, outputMint, amount }
- POST/api/v1/manifests/check{ manifest, observed? }
- GET/api/v1/analyticsAggregates
curl -s -X POST $HOST/api/v1/routes \
-H 'content-type: application/json' \
-d '{"inputMint":"USDC","outputMint":"GATE","amount":25}' | jq '.routes[0].status'Live mode
The app runs fully on mock adapters by default. Set HOOKWAY_MODE=live and HOOKWAY_RPC_URL to let the Token Inspector and /tokens/{mint}/inspect?source=chain read real mints via the SDK. Routing venues stay simulated until real venue adapters are integrated — the UI says so.
Writing explainable hooks
- → Return distinct custom error codes per rule. One generic error makes every failure unexplainable.
- → Derive every extra account from seeds. Accounts that need off-chain input make your token unroutable.
- → Keep the account list short. Many venues forward only 3–8 hook accounts.
- → Exempt pool vaults deliberately (max-wallet style hooks) and document it in restrictions.
- → If upgradeable, bump the manifest version on every deploy and say why the authority exists.