Jupiter and Metis
Use native CLMM quotes and external hook adapters without assuming public router admission.

The Metis adapter connects pool state to deterministic quotes and instruction construction. The optional grapl_amm::metis module exports GraplAmm, an implementation of the official Amm trait with native account decoding, core traversal, and native swap encoding. Hook support uses an injected external HookQuoteAdapter; policy implementations remain outside the generic library. No public Jupiter route, indexed pool, submission, or admission is claimed.
Update before quoting
from_keyed_account validates a native pool account. For a hooked pool, bind a compatible adapter with with_hook_adapter before collecting dependencies. get_accounts_to_update identifies pool, tick book, both mints, both vaults, and the configured hook's program and default account plan when applicable. The host supplies them through AccountProvider; a failed refresh invalidates previous quote state.
update_with_clock accepts an explicit coherent Clock snapshot. Standard update captures the injected Jupiter ClockRef, whose independent atomic reads do not themselves guarantee bank coherence. The host is responsible for obtaining matching account and time snapshots.
quote performs no account fetching or live-clock reads. It evaluates supported BeforeSwap logic, runs the core's CLMM traversal or virtual-reserve curve calculation, then evaluates supported AfterSwap logic on the resulting state. Replies enforce the configured profile and fee cap. ExactIn and ExactOut with FeeMode::Normal have native quote/encoding paths; ExactOut targets net output, and ExactIn requires a complete fill; partial consumption, output shortage, input-vault overflow, and invalid dependencies reject.
For actor-specific accounts, call get_accounts_to_update_with_context, fetch the returned dependencies, then use prepare_context(provider, clock, &context) to obtain an isolated refreshed clone. Failed preparation leaves the original instance unchanged. The external adapter supplies the exact HookAccountRequest plan; the generic loader validates it through core permissions. Account bounds are 16 extras and eight writes per callback, with the default limited to four read-only policy PDAs.
Choose the required context
| Pool | Adapter/context |
|---|---|
| No hook | No adapter; zero callback bits, PolicyOnly, System Program hook sentinel |
| Public time/fee example | Matching external adapter plus validated policy and Clock snapshot |
| Actor-dependent example | Matching adapter plus quote_with_context with claimed actor and opaque payload |
| Stateful hook | Matching effect evaluator, complete intent when required, contextual account plan, and coherent state |
| Unsupported hook/profile/callback combination | Explicit rejection until a compatible implementation is supplied |
Ordinary Amm::quote supplies empty context. It rejects an adapter requiring an actor or complete swap details. HookSwapContext contains actor, payload, optional HookSwapDetails, and ordered HookAccountRequest entries. The three economic examples share their actual policy evaluator with their off-chain adapter in examples/hooks/shared/src/metis.rs; they are optional examples, not native protocol policies. See Hooks and Metis compatibility for the complete authoring and construction flow.
Both mints and vaults must use supported classic SPL Token semantics. Token-2022 pool reserves, referral context, distinct user/transfer authority, and incomplete dynamic-account discovery remain unsupported. SingleRangeQuoter is a separate, narrower caller-supplied snapshot contract; its one-segment/no-hook limit does not describe GraplAmm.
quote_effects_with_context returns the AMM quote and simulated changes to existing account bytes. Each effect needs write permission in that callback; account creation, resizing, owner/lamport changes, executable writes, and protected aliases reject. Before-phase changes feed AfterSwap. The original snapshot is unchanged. Reward balances and counters belong in these separate effects, never in the AMM output amount.
Construct the native swap
get_swap_and_account_metas builds with the swap user and an empty payload. For contextual policies, use swap_with_context and preserve the quoted actor, payload, execution details, and account plan. The builder returns Swap::Placeholder and ordered native account metas, with exact non-signer hook extras and their requested write privileges appended. For ExactIn, encode_native_swap preserves explicit input, minimum output, and hook payload. ExactOut uses encode_native_swap_exact_out with the matching decision, target net output, and maximum input.
The builder requires user == token_transfer_authority and binds any explicit context actor to that user. Runtime execution still requires signer privilege and ownership of the actor token accounts. A claimed quote actor, fee payer, or AccountMeta flag is not authenticated wallet authorization. Routed PDA authority needs its own identity contract.
A quote is a snapshot result, not a reservation. Refresh for new policy/time state, and allow execution to reject if a time window closes or proof expires. The adapter does not silently ignore a policy to preserve an old quote.
Compare quote and settlement
Use coherent snapshots and compare actual input/output deltas with the quote in both directions and swap modes. Include policy rejection, output fees, stale state, and insufficient account coverage. Quote consistency describes the acceptance criteria.
Upstream contract and remaining work
The compiled interface is pinned to Jupiter AMM Interface revision 95bd18485e580625a39eb92a0c0ad2061579daad. QuoteParams has no wallet, signature, arbitrary proof payload, or timestamp field. grapl's contextual methods supplement that local API; they do not modify Jupiter's public quote request or register a router destination.
Public routing needs an accepted destination/encoder, actual route/CPI tests, account and compute-budget validation, and the separate Jupiter integration review. Local trait implementation and SBF parity do not complete those stages. The source-level external adapter contract is integrations/metis/HOOK_API.md.