Skip to main content
MakerStream is the bidirectional stream used by whitelisted makers. You receive RFQ requests and send signed quotes on the same connection. The connection is gRPC-web over WebSocket with protobuf payloads. Most integrations should use MakerStreamClient from injective-rfq-toolkit rather than hand-rolling framing.

Endpoint

EnvironmentMakerStream URL
Testnetwss://testnet.rfq.ws.injective.network/injective_rfq_rpc.InjectiveRfqRPC/MakerStream
MainnetContact TrueCurrent for the current production endpoint
Connection details:
PropertyValue
ProtocolgRPC-web over WebSocket
WebSocket subprotocolgrpc-ws
SerializationProtobuf
Framing[1 byte flags][4 bytes length BE][protobuf payload]
Keep-aliveSend ping roughly every second
Serviceinjective_rfq_rpc.InjectiveRfqRPC
MethodMakerStream
The indexer’s internal proto may use different package or method names. Public traffic uses the injective_rfq_rpc.InjectiveRfqRPC/MakerStream alias. Use the public alias shown above.

Connection sequence

Until the auth challenge is answered successfully, the stream may remain open but no request events arrive.

Message types

MakerStream responses are tagged by message_type.
message_typeDirectionMeaning
challengeIndexer -> makerOne-shot MakerChallenge; must be answered before requests are streamed
pongIndexer -> makerResponse to maker ping
requestIndexer -> makerRFQ request broadcast
quote_ackIndexer -> makerIndexer accepted or rejected the submitted quote payload
quote_updateIndexer -> makerQuote lifecycle update, when available
settlement_updateIndexer -> makerSettlement attempt or fill update, when available
errorIndexer -> makerStream or payload error
MakerStream requests you send are also tagged:
message_typePayload
pingHeartbeat
authMakerAuth response to the challenge
quoteSigned RFQ quote

Auth handshake

The indexer challenges the maker address announced in connection metadata. Sign the challenge with the same EIP-712 domain family used for quotes:
Domain fieldValue
name"RFQ"
version"1"
chainIdEVM chain ID (1439 testnet, 1776 mainnet)
verifyingContractRFQ contract converted from bech32 to EVM address

MakerChallenge

FieldTypeMeaning
noncestringHex-encoded 32 bytes. Decode to raw bytes for signing; do not hash the nonce first.
evm_chain_iduint64Chain ID for the EIP-712 domain.
expires_atsint64Unix milliseconds. Sign and reply before it expires.

StreamAuthChallenge

Type string:
StreamAuthChallenge(uint64 evmChainId,address maker,bytes32 nonce,uint64 expiresAt)
FieldEncoding
evmChainIdBig-endian integer word
maker20-byte EVM address derived from maker inj1...
nonceRaw 32 bytes from MakerChallenge.nonce
expiresAtBig-endian integer word

MakerAuth

Send the response as:
FieldMeaning
evm_chain_idSame value from the challenge
signature0x-prefixed 65-byte secp256k1 signature (`rsv, compact v=0/1`)

injective-rfq-toolkit handles framing, pings, and MakerChallenge auth when configured with auth fields.
from rfq_test.clients.websocket import MakerStreamClient

mm_ws = MakerStreamClient(
    endpoint=env.indexer.ws_endpoint,
    maker_address=mm_wallet.inj_address,
    subscribe_to_quotes_updates=True,
    subscribe_to_settlement_updates=True,
    auth_private_key=MM_PRIVATE_KEY,
    auth_evm_chain_id=1439,
    auth_contract_address=env.contract.address,
    timeout=15.0,
)

await mm_ws.connect()
If the stream connects and pongs return, but no request events arrive, debug the auth challenge first: wrong evm_chain_id, wrong contract domain, stale challenge, or a signature over hashed nonce bytes instead of raw nonce bytes are common causes.

Implementation checklist

  • Use the grpc-ws WebSocket subprotocol.
  • Send maker_address metadata on connect.
  • Answer MakerChallenge before expecting requests.
  • Start pinging immediately and continue roughly every second.
  • Treat rfq_id from each request as the correlation key.
  • Log every quote_ack, quote_update, settlement_update, and error.
  • Reconnect with backoff and re-authenticate after reconnecting.

ADL and position monitoring

MakerStream carries RFQ coordination events only. It does not replay every onchain position change. Auto-deleveraging (ADL) is handled by Injective’s exchange module through a position-offsetting mechanism. If one of your existing positions is offset by ADL, you will not receive an RFQ request or submit a quote for that close. Subscribe to the normal Injective derivative trade or position stream for your maker subaccounts and treat execution_type = OffsettingPosition as a real close event. ADL selection happens outside MakerStream. After an ADL close lands, update your inventory and close or resize the external hedge according to your risk policy. See Auto-deleveraging (ADL). Next: RFQ requests and Sending quotes.
Last modified on June 4, 2026