Manage Offchain-Signed Warp Fee Quotes
SkillCloud & infraCreate and read offchain-signed standing warp fee quotes on a deployed warp route, on both EVM and SVM chains. Use when asked to set, submit, update, or inspect standing (reusable, on-chain-expiring) offchain fee quotes for a warp route via the hyperlane warp quote command. One secp256k1 signer key works across EVM and SVM.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Manage Offchain-Signed Warp Fee Quotes skill
What this skill tells your AI
The instructions your AI receives, as published by hyperlane-xyz/hyperlane-monorepo in .claude/skills/warp-manage-offchain-quotes/SKILL.md and read by ahel’s review.
Create and read standing offchain-signed fee quotes on a deployed warp route using hyperlane warp quote (typescript/cli/src/commands/warp-quote.ts). Works on both EVM and SVM chains — the quote signature is secp256k1 ECDSA (Ethereum-style, recovers to an H160), so a single signer key is valid across protocols.
This is the general-purpose quote tool. The
set-moonpay-standing-quotesskill is a purpose-built wrapper for the CROSS/moonpay route specifically; use that one for MoonPay, this one for everything else.
Standing vs Transient
- Standing quote (
--ttl > 0): reusable until its on-chain expiry, stored on-chain. The amount must be wildcard — the EVM and SVM quote writers reject a concrete amount for a standing quote. The recipient may be wildcard (broadly reusable) or a concrete destination address (scoped). This is the only kind this command can create. - Transient quote (
ttl = 0, one-shot at submission time): NOT usable from this standalone command. Its storage is scoped to the create tx (EIP-1153 transient storage on EVM; on SVM an internally-generated client salt that is never returned), so it only exists inside the transfer tx that carries it.--ttltherefore must be> 0(the CLI demands it).
Two-Key Model (critical)
There are two distinct keys, do not conflate them:
| Key | Flag / env | Role |
|---|---|---|
| Quote signer | --quote-signer-key or HYP_QUOTE_SIGNER_KEY | 0x-hex secp256k1 private key that signs the quote. Its derived address MUST be in the route's quoteSigners allowlist (typescript/sdk/src/fee/types.ts) or the on-chain verification rejects the quote. |
| Tx submitter | --key.<protocol> (e.g. --key.ethereum, --key.sealevel) | Pays for and sends the on-chain submission transaction. Unrelated to signing. |
If the signer address is not in quoteSigners, the submission will revert — verify membership first.
Commands
Run from typescript/cli. Both require --warp-route-id.
create — submit a standing quote
cd <MONOREPO_ROOT>/typescript/cli && pnpm --silent hyperlane warp quote create \
--registry http://localhost:<port> \
--key.<protocol> "$SUBMITTER_KEY_VAR" \
--quote-signer-key "$HYP_QUOTE_SIGNER_KEY" \
-w <WARP_ROUTE_ID> \
--chain <origin-chain> \
--destination <remote-chain> \
--recipient <wildcard | native-address> \
--amount <wildcard> \
--max-fee <fee-token-smallest-units> \
--half-amount <fee-token-smallest-units> \
--ttl <seconds, > 0> \
[--target-router <native-router-address>]
Flag notes:
--chain= origin chain the quote is submitted on;--destination= the remote chain the quote applies to.--recipient/--amount:--amountmust be the wildcard sentinel (WarpQuoteAmountKind.wildcard) — concrete amounts are rejected for standing quotes.--recipientmay be wildcard or concrete; when concrete it is in the destination chain's native format (0x… EVM, base58 Solana).- When unsure which recipient to use, ask the user — do not silently default to
wildcard. A recipient is only valid in the destination chain's native format, so a value that worked for one destination (e.g. a Solana base58 key) is invalid when the destination is a different protocol (e.g. an EVM chain). If the user's requested recipient can't apply to this destination, or they said "same params" but the address format doesn't fit, stop and confirm the intended recipient (concrete address vs.wildcard) before submitting.
- When unsure which recipient to use, ask the user — do not silently default to
--max-fee+--half-amount: the raw linear fee-curve parameters, expressed in the configured fee token's smallest units — scaled by that token's decimals, not necessarily chain-native wei/lamports, so check the fee token's decimals. If the ask is in bps, convert to these raw params viabpsToRawFeeParams(EVM usesMaxUint256/ 10^36, SVM usesu64max / 10^8) rather than asking the user for raw numbers — but never invent fee economics if given neither bps nor raw values.--ttl: seconds; on-chain expiry = now + ttl. Must be> 0.--target-router: cross-collateral only. Submits against a specific router-keyed leaf, in the destination chain's native address format. Omitting it auto-resolves ONLY when the destination has a single match (the one router-keyed leaf if exactly one matches, else theDEFAULTleaf); if MORE than one router-keyed leaf matches the destination, the CLI does NOT guess — it exits asking for--target-router, so pass the specific leaf. On SVM there is no cascade: the signedtargetRoutermust exactly match a deployed leaf, so only target a router that actually exists (else drop the flag to hitDEFAULT). Don't set it for single-collateral routes.
read — inspect standing quotes
cd <MONOREPO_ROOT>/typescript/cli && pnpm hyperlane warp quote read \
--registry http://localhost:<port> \
-w <WARP_ROUTE_ID> \
[--chain <chain>] \
[--recipients <native-addr> --recipients <native-addr> ...] \
[--out <file.yaml>]
- Read-only, no keys.
--chainscopes to one chain (defaults to all chains in the route).--recipients: extra recipient addresses to probe on protocols whose standing-quote storage is non-enumerable (EVM — you must know the recipient to look it up). Ignored on protocols that enumerate on-chain (SVM lists them for you). Accepts native format per chain (0x… / base58); the CLI auto-detects protocol and converts to bytes32, skipping anything that isn't a valid address.
Execution Flow
- Verify the signer is allowlisted. Derive the address from the quote signer key and confirm it appears in the route's
quoteSigners. If not, stop — the quote would be rejected on-chain. - Start the HTTP registry per
/start-http-registry— add--writeModeforcreate(it writes the quote on-chain);readneeds no--writeMode. Note the port + task ID. - For create: first
readthe current standing quotes for the lane so you can show old→new. Confirm the recipient is valid for the destination protocol; if it's ambiguous or a format mismatch, ask the user before submitting rather than defaulting towildcard. Then runcreate. Summarize the lane (origin→destination, recipient/amount scope, maxFee/halfAmount, TTL) in plain language before the raw output. - For read: run and show output directly (no confirmation — read-only). On EVM, remember concrete recipients must be supplied via
--recipientsto be visible. - Stop the HTTP registry per
/stop-http-registry, even on failure.
Caveats
- One signer key, all protocols. Because verification recovers an H160 from a secp256k1 signature, the same
--quote-signer-keyworks for EVM and SVM. The address just has to be inquoteSigners. - Signer ≠ submitter.
--quote-signer-keysigns;--key.<protocol>pays. Supplying only one of them is a common mistake. --ttlmust be > 0. Transient (ttl=0) quotes cannot be created from this command — they only live inside a transfer tx.--target-routeris cross-collateral only and expects the destination chain's native router address; leave it off otherwise and rely on auto-resolution.- EVM reads need
--recipientsfor concrete (non-wildcard) recipients since EVM storage isn't enumerable; SVM reads enumerate on-chain. - For the CROSS/moonpay route specifically, prefer
/set-moonpay-standing-quotes.
Signals
- GitHub stars
- 75
- Forks
- 601
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
warp-manage-offchain-quotes- Source
- github.com/hyperlane-xyz/hyperlane-monorepo