Basic Market Making API
This page explains how market makers can interact with the Liquorice RFQ WebSocket API using their own inventory
1. Getting started
Connecting to maker API
Production:
wss://api.liquorice.tech/v1/maker/ws
Include the following headers with the WebSocket request
Authorization: Basic <base64(maker:token)>index(optional) - index of the connected client (between 0 and 9). Allows multiple connections with the same credentials.
The WebSocket server sends Ping message every 30 seconds.
2. Managing token approvals
Standard approvals
Token approval must be granted solely to the Liquorice Balance Manager smart contract address. Giving standard approval is the most gas efficient way to trade. Important note: providing approval to any other Liquorice address outside of Balance Manager may compromise the security of your funds, as it does not guarantee the same level of protection. Approvals should be given strictly to the Balance Manager address.
Permit2
Liquorice integrates with the Uniswap Permit2 contract.
To use Permit2, first grant standard token approval to address: 0x000000000022d473030f116ddee9f6b43ac78ba3
3. Publishing Price Levels
Maker needs to publish indicative quotes (price levels) to the API. These should be published for every supported pair. Note that WETH/USDC and USDC/WETH are considered different pairs and should be published separately.
Published price levels will expire in 30 seconds. Desired frequency of update is no more than once every second.
Schema
Assuming that trader wants to swap 2 WETH for USDC, the maker would be buying 0.5 WETH for 2999.5 USDC, 1 WETH for 3000.5 USDC, and another 0.5 WETH for 3002.0 USDC
Your smallest level sets your minimum trade size — RFQs below it are not routed to you, as RFQs above your total depth already are not.
4. Receiving RFQ
When a trader or intent system requests a quote, Liquorice forwards the request to market makers using the following format:
The RFQ will include either
baseTokenAmountorquoteTokenAmount, but not both.When
baseTokenAmountis specified, thetrader(order initiator) is requesting the amount ofquoteTokenthey would receive in exchange for a specific amount ofbaseToken.When
quoteTokenAmountis specified, thetrader(order initiator) is requesting the amount ofbaseTokenthey need to provide to receive a specific amount ofquoteToken.
intentMetadata- For the moment, only CoW Protocol is supported. If this parameter is absent, it means that the quote is requested for another intent system.
5. Providing Quote
Send the quote response through the same WebSocket connection using the following format:
Market makers can provide multiple quote levels with different amounts, but the quoted amounts must not exceed those specified in the RFQ.
Example For an RFQ where:
baseToken = ETH
quoteToken = USDT
baseTokenAmount = 1 ETH
The resulting quote may contain these levels:
Level 0: Exchange 1 ETH for 3,000 USDT
Level 1: Exchange 0.5 ETH for 1,502 USDT
Level 2: Exchange 0.1 ETH for 310 USDT
Quote level Lite
Use this type of quote level for simple and gas-efficient swaps.
Note: supports only Standard approvals
Quote level Extended
Use this quote level type for customizations that require hooks and interactions.
It supports both Standard and Permit2 approvals.
Using lending pools
Liquorice allows market makers to settle trades using borrowed funds, provided they have posted collateral equal to at least 25% of the quoted amount.
Consider the following example: a market maker receives an RFQ where a trader intends to exchange WETH for USDC. If the market maker does not have USDC in their inventory, they can borrow it from the lending pool—assuming they have supplied collateral (in any token) worth at least 25% of the quoted USDC amount.
For instance, if the quote is to exchange 0.3 WETH for 1,000 USDC, the market maker can post 250 USDT as collateral and borrow 1,000 USDC from the pool.
When the trade is settled, the 0.3 WETH will be added to the locked collateral alongside the market maker’s initially supplied 250 USDT. As a result, the market maker’s position in the pool will consist of 0.3 WETH and 250 USDT as locked collateral, with 1,000 USDC as outstanding debt.
To settle a trade using borrowed funds, the market maker must use the Extended Quote level and specify token amounts in the toSupply field of baseTokenData and the toBorrow field of quoteTokenData.
baseTokenData.toSupply: the amount (e.g., 0.3 WETH) that the trader will supply and which will be added to the locked collateral on behalf of the market maker.quoteTokenData.toBorrow: the amount (e.g., 1,000 USDC) to be borrowed on behalf of the market maker and sent to the trader.
The system will automatically generate the transaction payload and forward it to the origin of the intent.
To withdraw the 0.3 WETH collateral, the market maker must first repay a sufficient portion of the 1,000 USDC debt.
6. Error handling
If the quote payload is not valid, WS API will send a message in the following format
type
When it is sent
metadata
bad_payload
The message could not be deserialized at all
(absent)
quote_validation
A quote level failed validation (token/settlement mismatch, amount bounds, sum invariants, signature recovery mismatch, level count)
{ rfq_id }
quote_deadline
The quote arrived after the aggregator stopped waiting for this RFQ
{ rfq_id }
quote_simulation
The quote was well-formed but failed on-chain simulation
{ rfq_id, data } — data is the optional revert payload
missing_rfq
rfqId does not match any live RFQ (unknown, or already answered/expired)
{ rfq_id }
price_submission
A priceLevels message was rejected (bad levels, unknown solver, unsupported chain)
{ chain_id, base_token, quote_token }
quote_slippage
Quote price deviates from your own submitted price levels
{ rfq_id, actual_bps, max_bps }
Example
7. Receiving notifications
Notification types
Settlement
Sent when RFQ is about to be settled on-chain
Suspension
Sent when the aggregator temporarily stops routing RFQs to you because your quote availability fell below the expected ratio. RFQs resume automatically after until
8. Getting quote summary
Use the following endpoint to retrieve an extended information for the provided quote. Quote summary includes information such as originating solver RFQ and resulting solver quote with the competing quote levels from other market makers, and settlement result if the resulting solver quote was used to settle the trade on-chain.
URL: https://api.liquorice.tech/v1/maker/quote-summaries/{rfq-id}
Method: GET
makerQuote.statuscan be one oflive,settled,expiredormissedDeadlinefield
settlementResultshows data on on final settlement which can be used, for example, to compare price provided by you with the winning price. If this field is "null", it normally means that settlement did not occurfield
competing levelsshows prices provided by other liquidity sources connected to Liquorice
9. Getting info on settled trades
When a trade executes on-chain, the Liquorice settlement contract emits a TraderOrder event containing information about transferred amounts. The event reflects actual token transfers, including cases of partial fills, and always shows the final amounts transferred on-chain.
Note: rfqId is indexed and is a dynamic string, so the log topic is keccak256(rfqId), not the readable UUID. The unhashed value is not available from the log — match on the topic hash.
Last updated