- Collects user intents from various sources.
- Broadcasts these intents to connected solvers in real-time.
- Tracks the on-chain status of all transactions.
We recommend the order server for its built-in safety checks, but for on-chain orders it is entirely optional. Not every intent reaches the chain, though — lintent.org, for one, does not emit intents on-chain. And any intent you read off the chain yourself, you must hydrate and validate very thoroughly.
Order subscription
You can collect orders in two ways: a WebSocket subscription that pushes orders to you, or a GET endpoint you poll. We recommend the WebSocket subscription. Both methods can be found in the lintent.org demo implementation. If you use the GET endpoint too aggressively, you may be throttled or temporarily timed out. You can find swagger documentation on api interfaces on https://order-dev.li.fi/docs.You may receive the same order more than once through the WebSocket interface. It happens each time an intent is ingested from a source of truth, and the later copies can carry extra context. Use the
orderId to identify an intent, and keep the extra context when a later copy brings it.Order Server events
The WebSocket host iswss://order.li.fi (production) or wss://order-dev.li.fi (development). Messages are JSON frames of the form { "event": string, "data": ... }:
user:vm-order-submit— a new order is available. The data is returned similarly to how it was submitted: the full order plus metadata (order id, status, timestamps, quote id).intent:transaction-observed— lifecycle updates when an order becomesDelivered,Finalised, orRefunded.- Heartbeat — the server sends
{"event": "ping"}every 5 seconds; reply with{"event": "pong"}within 10 seconds or the socket is closed. This is used to disconnect misbehaving clients and for debugging purposes. You can find an example implementation here.
Order Validation
LI.FI Intents allows highly customizable orders, so you must add your own validation to confirm you support each order relayed to you. Below, whitelisted means trusted and validated by you. When a token must be whitelisted, it means you have vetted the token. If a validation layer is whitelisted, it means you have vetted the validation layer, etc. Whitelisted does not mean permissioned by a central entity. This list aims to cover every validation a solver must implement. It may look long, but you have likely already implemented most of these checks.General Validation
fillDeadline: Ensure you have sufficient time to fill the order:- Time to fill on the destination chain, including potential source chain finality.
expires: Ensure you have enough time to fill, relay, and claim the order:- Time to fill on the destination chain, including potential source chain finality.
- Time to send message validation proof to the input chain.
- Time to claim the order after validation has been delivered.
- Validation layer: Ensure you support submitting proofs (and, if not automatic, also relaying) to the validation layer. Additionally, the
inputOracleandoutput.oraclemust be of the same validation layer. - Ensure you have whitelisted every
inputtoken. If one input token is malicious, the order may be unclaimable. Additionally, for blacklistable tokens like USDC, ensure you are not on a blacklist.- If an order has a 0 input or output of a token you have not whitelisted, the order may not be fillable. Be careful about filling orders containing unfamiliar tokens.
- For each output:
output.chainIdis whitelisted.output.oracleandinputOracleare correctly configured regardingoriginChainIdandoutput.chainId. On-chain configs are immutable, so this can be done once for each chain pair.output.settleris whitelisted.output.contextis decodable, and the order type is supported and compatible withoutput.settler.output.tokenis whitelisted. Additionally, for blacklistable tokens like USDC, ensure that neither you nor the recipient is on a blacklist.- If an order has a 0 input or output of a token you have not whitelisted, the order may not be fillable. Be careful about filling orders containing unfamiliar tokens.
- You have sufficient tokens for
output.amount. - If the output has
calldata, ensure you can execute it and other outputs atomically. For outputs on different chains, you may have to whitelist recipients if there iscalldata.- On OP-chains, CrossL2Inbox needs to be blacklisted in the entire call tree. If similar contracts exist on another chain, they also need to be blacklisted.
- Neither
call.lengthnorcontext.lengthis more than 65,535 bytes long. - Validate the context depending on order type. For Bitcoin specifically, ensure the encoded multiplier is relative to the Bitcoin value.
- If the order has multiple outputs, ensure you can fill all outputs and the first output is set to your solver identifier. If all outputs are on the same chain, a single
fillOrderOutputscall fills them all as a protective measure. - If the InputSettler has any fees, check for an imminent fee change.
On EVM and Tron, input tokens are encoded as
uint256; the first 12 bytes may hold a lock tag and the address is the last 20 bytes. A Solana order instead carries one MandateInput { token: Pubkey, amount: u64 }. In Solana feed messages, top-level addresses render as base58, while output oracle, settler, token, and recipient values remain 32-byte fields.Escrow Validation
- Ensure no input tokens are fee on transfer.
- Ensure every
inputstoken has no set bits in its upper 12 bytes. - Ensure the order has already been opened, either through the
event Openorfunction orderStatusOR you are opening the order throughfunction openForbefore filling the order.
Solana Validation
Solana orders are escrow-only, so the Compact checks below do not apply. On top of the general validation, check:- Identity fields. Re-derive every 32-byte identity in the order —
outputs[].settler,outputs[].oracle,inputOracle— from the published program IDs and seeds (or pin the published addresses as golden values) and check them against the identity matrix. Reject on any mismatch. u64bounds.MandateOutput.amountand Dutch-auctionslopevalues aboveu64::MAXmake an output unfillable on Solana (Auctions).- Callbacks. The default Solana output settler requires
callback_datato be empty and rejects fills otherwise. - Recipient accounts. For SPL outputs,
recipient_token_account.ownermust equalrecipient; you may pay ATA rent when the recipient has no token account yet. - Order size. A single-output order with no calldata and a standard context is always safe to finalise. Anything beyond that requires thorough validation against the finalise transaction limit — see Order size for the exact bound.
Compact Validation
- Ensure every
inputtoken uses the sameallocatorId. If thelockIdvalues differ, check the lock expiry for every one of them; if they are all equal, one expiry check is enough. - Ensure the potential
reset periodfor a resource lock extends beyond theexpiryAND there is no active withdrawal. - Ensure the
allocatorIDis whitelisted. The allocator can block claims from processing (by withdrawing signatures or reusing nonces.)- The allocatorID is part of the
lock tagforinputs(first 12 bytes). - Optionally, ensure the user has sufficient tokens. This should have been validated by the allocator, though.
- The allocatorID is part of the
- Ensure the user provides an ECDSA signature or they have a whitelisted emissary registered or you register the claim on-chain before filling the claim.
- Note: If any of these actions are taken, the signature can be assumed to be trusted.
- Emissary signatures cannot be registered on-chain. The emissary must be trusted not to redact a signature.
- Validate the
allocatorData. You may have to do an on-chain call. - Validate that the allocator
noncehas not been spent previously by any user. The Order nonce is not a user nonce.
Signature Validation
TheStandardOrder is what you pass to every function on the input chain. Once hydrated with a signature, it also lets you check that an order is valid.
The StandardOrder struct will be signed and stored as a witness in the appropriate lock/claim structure. For TheCompact, this is:
On-chain Order Broadcast
When intents are registered on-chain, they can be broadcasted on the Input Settlement contract through theIntentRegistered event:
When collecting permissionless orders, ensure they are properly validated and co-signed. The order server helps with validation, but on-chain, anyone can emit a fraudulent message.

