| name | injective-rfq-integrations |
| description | Integrate Injective RFQ taker flows into browser apps and operational quote monitors. Use this skill when building, reviewing, or debugging RFQ gateway autosign settlement, Web3Gateway AuthZ setup, manual TakerStream quote collection, client-side gateway-style quote selection, RFQ open/close flows, gateway prefetch, optimistic position updates, conditional TP/SL intents, quote uptime probes, market-readiness checks, or mainnet RFQ frontend integrations. Covers mainnet parameters, canonical decimals, quote windows, signer slots, market discovery, quote-hit diagnostics, and production RFQ gotchas. |
| license | MIT |
| metadata | {"author":"ck","version":"1.0.0"} |
Injective RFQ Integrations
Use this skill when adding Injective RFQ to a frontend or when building an RFQ
quote monitoring tool. Keep the main flow simple: use the RFQ gateway when you
want managed settlement, and use client-side gateway mode only when the app is
ready to own quote collection, selection, broadcast timing, and reconciliation.
Mainnet Parameters
The canonical mainnet RFQ contract address is:
export const RFQ_CONTRACT_ADDRESS = 'inj12stwq95jet57edcu4a65r48r46s9rzrs938n8k'
export const RFQ_WS_URL = 'wss://rfq.ws.injective.network'
export const RFQ_GATEWAY_URL = 'https://rfq.gateway.grpc-web.injective.network/'
export const RFQ_CHAIN_ID = 'injective-1'
export const RFQ_EVM_CHAIN_ID = 1776
export const RFQ_COLLECT_QUOTES_MS = 500
RFQ_CHAIN_ID is the Cosmos chain ID used in RFQ quote payloads and Cosmos
sign docs. Do not set it to 1776. RFQ_EVM_CHAIN_ID is the numeric Injective
EVM chain ID used in EIP-712 domains, Web3Gateway signatures, and
quote.evmChainId.
Choose The Path
Use the managed gateway autosign path for production browser trading when
latency is acceptable and you want the backend gateway to own quote collection
and settlement assembly:
- Connect an EVM wallet and derive the user's Injective address.
- Create a local ephemeral autosign key for that wallet.
- Grant AuthZ to the autosign key and to the RFQ contract through
Web3Gateway fee payer.
- Build canonical RFQ input from market metadata and mark price.
- Call
IndexerGrpcRfqGwApi.fetchPrepareAutoSign.
- Sign the returned
TxRaw exactly as received.
- Insert both autosign and fee-payer signatures in decoded signer order.
- Broadcast and poll the tx for final reconciliation.
Use client-side gateway mode when the browser needs lower click-time latency or
special quote selection. In that mode, the app is moving gateway/indexer duties
to the client: TakerStream request ownership, ACK mapping, quote collection,
quote selection, accept transaction preparation, per-wallet serialization,
optimistic state, and chain/indexer reconciliation. Read
references/client-side-gateway.md
before implementing it.
Use manual TakerStream diagnostics when you only need raw quote behavior,
maker identity, or quote uptime checks. Diagnostics should not silently turn
into settlement; settlement requires all client-side gateway responsibilities.
Client-Side Gateway Mode
Client-side gateway mode is a latency optimization, not just a transport
choice. The gateway behaves like a coordinator/indexer: it opens RFQs, tracks
ACKs, collects maker quotes, chooses executable quotes, assembles settlement,
and reconciles state. A browser implementation must replace those duties
explicitly instead of only opening a WebSocket.
- Keep one active taker stream owner per wallet/session and reconnect
deliberately on wallet changes.
- Track
clientId -> rfqId ACK replacement. Quotes can arrive before ACK, and
ACK ids may differ from local client ids.
- Use short, bounded collection windows. Start the window from ACK or the first
matching quote, not from arbitrary UI time.
- Sort executable quotes deterministically: lower price is better for long
takers, higher price is better for short takers.
- Validate quote freshness, signed payload fields, maker eligibility, market,
direction, quantity, TTL, chain ids, contract, and worst-price guardrails.
- Prefetch account sequence and timeout height before selection when quote TTLs
are tight. Avoid post-selection RPCs in sub-second paths.
- Serialize accepts per wallet. Parallel accepts can race account sequence even
when they target different markets.
- Treat optimistic position state as provisional until chain/indexer data
confirms it. Roll back cleanly on post-match broadcast or chain failure.
- Keep a managed gateway fallback or recovery path unless the product has
operational monitoring for quote hit rate, maker failures, and stuck state.
Production Rules
- Do not rebuild gateway transactions. Sign the returned
bodyBytes and
authInfoBytes exactly.
- Do not assume autosign is signer index
0. Decode AuthInfo.signerInfos,
normalize pubkeys, and fill signatures in decoded signer order.
- Normalize protobuf-wrapped pubkeys.
AuthInfo.signerInfos[].publicKey.value
can be 0a21...raw-key while SDK public keys are raw 33-byte compressed
keys.
- Canonicalize every signed decimal string. RFQ signatures bind string bytes,
so
"110.0" and "110" are different values.
- Use human price ticks for RFQ prices. Exchange
minPriceTickSize is often
quote-decimal scaled.
- Position close is RFQ too: opposite direction, same quantity,
margin: "0".
- After a successful close, cancel active TP/SL intent lanes for that market.
- Keep quote collection windows short. Production retail flows should start
with
500 ms. Latency-sensitive taker bots can use 50-100 ms, but should
measure quote hit rate because some makers respond slower than 50 ms.
- For maker-routed flows, expose
onlyMakers, excludeMakers, minTtlMs,
collectMs, priceCheck, and gasLimit as explicit operational knobs.
- Direct RFQ accept paths should default near
2_000_000 gas. Mainnet
synthetic executions have used about 1.34M gas, so 1_000_000 can fail
before revealing the maker's semantic error.
- Do not import
TxInclusionStrategy or set txInclusion unless the installed
SDK actually exports it. A missing export breaks Vite at runtime.
Fast Gateway Execution
For a snappy browser UI, prefetch RFQ gateway orders when form inputs are valid
and stable, then reuse the prepared order on submit only if all submission
dependencies still match.
- Gate prefetch behind an explicit user or app setting. Background prepare
traffic is useful, but it should be observable and easy to disable.
- Debounce and limit prefetches. Restart when quantity, worst price, direction,
market, margin, leverage, subaccount, autosign address, or account sequence
changes.
- Cache prepared gateway orders with a short TTL and a dependency fingerprint.
Treat account sequence changes as invalidation.
- Consume a prepared order once a submit path uses it. Never reuse the same
prepared tx or RFQ payload for a later click.
- If a matching prefetch is in flight on submit, wait only behind a bounded
timeout. Fall back to click-time prepare when it stalls.
- Build close-position prepared orders with the same gateway path: opposite
direction, position quantity,
margin: "0", and a worst-price guardrail.
- Track prepare lifecycle in observability: requested, skipped, cache hit,
cache miss, stale dependency, timeout, success, and failure.
Browser Taker UX Lessons
When integrating RFQ taker flow into a browser app, keep protocol details out
of user-facing states and serialize trade submission:
- Prequote or warm RFQ requests can improve click-time latency, but still
validate quote freshness, maker allowlists, slippage, and prepared RFQ input
at final submit time.
- Treat
no quotes received within wait time [rfqID: ... taker: ...] as an
internal diagnostic. User-facing copy should be short, such as
Order failed, please try again. Log the RFQ ID and taker details for
developers instead.
- Disable all trade buttons for the wallet while an open or close RFQ is in
flight. Matching is not enough; release the lock only after the accept tx is
confirmed or the flow fails.
- Do not let parallel RFQ accepts from the same wallet race the account
sequence. One per-wallet in-flight lock is safer than per-card or
per-position loading state.
- If a UI searches markets, prefer scroll-and-highlight over filtering cards out
of the grid. Filtering can resize the target card and make the trading form
feel unstable.
Prequote Price Semantics
Separate display prices from RFQ guardrails:
- Button prices should show the best live maker quote when available.
- Fallback display prices can use index price plus or minus the user's
slippage setting, but label them as estimates.
- Prequote RFQ
worstPrice does not have to equal user slippage. A client-side
gateway can use tighter RFQ prequote tiers for quote discovery, then escalate
after misses.
- User slippage still belongs in final submit guardrails and can affect sizing
indirectly when quantity is derived from quote notional.
- Worst price is a guardrail, not an expected execution price. Seeing better
maker quotes than the guardrail is normal.
RFQ Input Rules
For open requests, derive quantity from stake, leverage, and mark price:
quantity = floor((margin * leverage) / mark, minQuantityTickSize)
- long worst price =
mark + slippage, rounded up to price tick
- short worst price =
mark - slippage, rounded down to price tick
For closes:
- direction is the opposite of the open position side
- margin is exactly
"0"
- quantity is the position quantity, floored to quantity tick
- worst price is still a guardrail
Worst price is a guardrail, not an expected execution price. Seeing better
quotes than mark +/- slippage is normal.
Optimistic Position UX
Optimistic RFQ frontend execution means updating user-visible state at gateway
match time, then reconciling against the chain and indexer. Chain-side
optimistic execution can make settlement faster, but the UI must still treat
pre-confirmation state as provisional.
- Show the submitted toast immediately on click, before slow validation,
prepare, signing, or broadcast work.
- When the gateway returns matched quote details, emit the filled toast
immediately and update the positions table before chain confirmation.
- Use the matched quote response for filled quantity and average price. Do not
display requested quantity in fallback filled or settled toasts.
- Keep the chain-success toast quiet when a matched filled toast already fired.
- On a post-match broadcast or chain failure, roll back the optimistic position
and show exactly one error toast:
Order reverted, please try again.
- Suppress duplicate generic errors from the same failure path, such as
Contract execution failed, once the revert toast has been shown.
- Preserve optimistic positions across market switches, stream restarts, and
initial refetches until real indexer data confirms or invalidates them.
- Clear optimistic state on real position insert/update/delete for that market,
explicit rollback, account reset, or expiry.
- While a market has an active optimistic position, keep stream suppression
timers re-armed instead of letting stale fetched rows replace the provisional
row.
- Disable close-position actions for optimistic rows until the position is
confirmed by chain/indexer data.
Focused tests should cover event order, immediate submitted toast, matched
toast before broadcast completion, prepared-order reuse and consumption, stale
dependency invalidation, in-flight prefetch timeout, rollback, duplicate error
suppression, stream restart preservation, and disabled close actions.
Maker Routing And Short TTL
When a flow must avoid specific makers, use manual TakerStream quote
collection and accept only filtered quotes. Gateway settlement is still the
recommended browser path, but if the gateway accepts the first quote from a
distressed or underfunded maker, the whole settlement can fail. Track quote
diagnostics per maker: maker address, price, quantity, TTL at selection,
rejection reason, and on-chain execution error.
For makers with sub-second or low-second TTLs, avoid post-quote RPCs. Prefetch
account sequence and timeout height, collect for the minimum usable window,
build the accept message locally, and broadcast immediately. A quote with
about 1.4s TTL can expire if you wait 500 ms and then fetch sequence/block
height after selection.
AuthZ Setup
Use Web3Gateway fee payer for wallet-signed setup transactions so users do not
need an INJ balance just to authorize RFQ.
Grant two groups:
- App/autosign grantee: exchange order messages plus
/injective.wasmx.v1.MsgExecuteContractCompat
- RFQ contract grantee:
/injective.exchange.v2.MsgPrivilegedExecuteContract,
/injective.exchange.v2.MsgBatchUpdateOrders, and
/cosmos.bank.v1beta1.MsgSend
If setup asks users to pay gas, the integration is bypassing Web3Gateway.
Known Maker Failure Modes
Record maker-level RFQ errors instead of collapsing all quote failures into a
single settlement error. Useful categories observed on mainnet include:
- maker position below maintenance, often from a liquidated account still
quoting
- insufficient maker balance for the quote minimum quantity
- quote expired before the execution block
- out of gas before maker semantic checks completed
Quote Probe / Uptime Mode
For tools that only test whether market makers are quoting, read
references/quote-probe-uptime.md. A probe can send
RFQ requests and collect quotes without accepting them on-chain. The taker key
must sign RFQ requests, but the wallet does not need funds unless a quote is
accepted.
Measure bid/short and ask/long separately:
RFQs sent: RFQ requests opened for that side
Requests quoted: RFQs that received at least one MM quote
MM quotes: total raw maker quote responses
Best bid / best ask: best sorted price for the side
MM quotes can exceed RFQs sent because one RFQ can receive multiple maker
responses. For example, 100 RFQs, 69/100 requests quoted, and 140 MM quotes means 69 requests got at least one response and those requests received
140 total maker quotes.
Conditional TP/SL
TP/SL is a signed RFQ close intent, not an orderbook reduce-only limit:
- long position TP:
mark_price_gte, direction short, margin "0"
- long position SL:
mark_price_lte, direction short, margin "0"
- short position TP:
mark_price_lte, direction long, margin "0"
- short position SL:
mark_price_gte, direction long, margin "0"
Fetch epoch and lane_version from the RFQ contract before signing. After
editing or canceling a lane, re-query before signing fresh intents.
References