0-Conf for Elements and Liquid: A Technical Explainer
New 0-conf infrastructure for Liquid and different Elements-based deployments is right here.
As a Blockstream-operated service part, it aggregates mempool visibility for Liquid transactions. Nodes throughout the community report once they have seen a transaction, and this service exposes that information. As an integrator, you should utilize it as one enter when deciding whether or not to simply accept a zero-confirmation fee, significantly in swap and different low-latency settlement flows.
The 0-conf service exists to make that sign accessible in a typical, queryable kind. Instead of constructing bespoke federation monitoring, you’ll be able to ask one service how extensively a transaction has been noticed throughout configured community tiers.
We are particularly grateful to members of the Liquid Federation for their partnership in the course of the beta phases. Their swap workloads, operational suggestions, and testing helped validate the API design.
Why 0-Conf?
Liquid transactions are at the moment thought-about last as soon as they’re in a block that has one different block on prime of it. In observe, which means ready for two confirmations (two minutes) earlier than treating a fee as settled on the Liquid Network.
Swap companies, exchanges, and different functions that settle for Liquid funds usually want sooner settlement instances. Accepting transactions with zero confirmations reduces wait time, however it introduces double-spend danger.
This new 0-conf infrastructure helps integrators assess that danger. It’s a hosted API that stories how extensively a given Liquid transaction has propagated throughout the community. It stories how extensively a transaction has been noticed throughout configured community statement tiers. Broad visibility is a helpful sign for non-replace-by-fee (non-RBF) transactions, however it doesn’t get rid of danger fully.
For instance, on Elements, if a transaction will not be RBF-enabled, a node retains the primary conflicting spend of the identical inputs it accepted. A subsequent transaction reusing these inputs is ignored, even with the next charge. Under the belief that federation members act actually, extensive mempool visibility for a non-RBF transaction suggests it’s extremely unlikely to be double-spent earlier than affirmation.
Understanding Liquid’s Trust Model
As a federated sidechain, Liquid blocks are produced by a subset of members known as functionary operators. For a fee that hasn’t opted into RBF, extensive statement protection is a powerful sign that the community has converged on one model of the spend, as long as the federation members are appearing actually and their mempools are behaving usually.
0-conf doesn’t assure {that a} seen transaction will likely be confirmed. It merely tells you which ones statement nodes have reported seeing a given transaction of their mempool.
As a outcome, 0-conf offers you an correct, real-time view of community mempool visibility. But whereas it’s a dependable foundation for making an acceptance resolution, visibility continues to be solely an indicator, not a receipt for settlement functions.
Observations in Practice
Each API response contains an observations object which maps statement tiers to counts of what number of configured nodes in every tier have reported seeing the transaction.
Each tier stories:
- Seen: variety of nodes in that tier which have reported the transaction
- Total: variety of nodes configured for that tier
For instance:
{
"txid": "<txid>",
"observations": {
"bridge": {
"seen": 1,
"whole": 2,
},
"public": {
"seen": 0,
"whole": 8,
},
"functionary": {
"seen": 12,
"whole": 15,
}
}
}
Note that the API doesn’t embrace a discipline indicating {that a} transaction is protected to simply accept with out affirmation. Acceptance coverage is application-defined.
Choosing REST or WebSocket
Both interfaces return the identical statement information. The distinction is the way you obtain updates.
REST
Best for easy, stateless checks: you’ve gotten a txid and need the present statement counts proper now.
- Straightforward to combine from any HTTP consumer, cron job, or backend service
- No connection to keep up; every request is unbiased
- Easy to retry on failure
Tradeoffs:
- Observations change over time as extra nodes see the transaction. REST solely returns a snapshot at request time, so you need to ballot in case you are ready for protection to extend
- Suited to “examine as soon as earlier than accepting” or low-frequency standing lookups, much less ideally suited for watching propagation in actual time
WebSocket
Best for latency-sensitive flows: you might be ready for statement counts to achieve your threshold and wish to act as quickly as they do.
- Subscribe to a txid and obtain a snapshot instantly, then additional snapshot messages at any time when observations change
- Multiple txids could be subscribed on a single connection
- Lower latency than polling; no repeated HTTP requests when you wait
Tradeoffs:
- Requires sustaining a persistent connection and dealing with disconnects, reconnects, and resubscription
- More consumer logic than a single REST name (subscribe, unsubscribe, parse message sorts, deal with errors)
REST Interface
GET /api/v1/zeroconf/:txid
Returns a JSON response with the transaction ID and present observations for that transaction:
{
"txid": "<txid>",
"observations": {
"bridge": {
"seen": 1,
"whole": 2,
},
"public": {
"seen": 0,
"whole": 8,
},
"functionary": {
"seen": 12,
"whole": 15,
}
}
}
WebSocket Interface
WS /ws/v1/zeroconf
Opens a WebSocket connection. You then handle subscriptions over it by sending JSON messages: one to start out watching a txid, one to cease.
Subscribe
{ "motion": "subscribe", "txid": "<txid>" }
Unsubscribe
{ "motion": "unsubscribe", "txid": "<txid>" }
You can keep a number of simultaneous subscriptions on the identical connection
Server messages
On profitable subscription:
{
"motion": "subscribed",
"txid": "<txid>",
"message": "subscription created"
}
On snapshot or replace (despatched at any time when observations change):
{
"motion": "snapshot",
"txid": "<txid>",
"observations": {
"bridge": {
"seen": 1,
"whole": 2,
},
"public": {
"seen": 0,
"whole": 8,
},
"functionary": {
"seen": 12,
"whole": 15,
}
}
}
On expiration:
{
"motion": "expired",
"txid": "<txid>",
"message": "subscription expired"
}
On error:
{
"motion": "error",
"cause": "bad_txid",
"message": "TXID should be 64 hex characters"
}
Subscriptions expire mechanically after a server-configured timeout, however you’ll be able to re-subscribe if you happen to nonetheless want updates.
Data Retention
The server periodically removes transactions from reminiscence. Use this service to examine latest mempool visibility, not as a long-term transaction index. Results could also be incomplete or absent for transactions which have already been confirmed or have been within the mempool for an prolonged interval.
Feedback and Bug Reports, Please!
If one thing seems incorrect, or you’ve gotten strategies for bettering the API or documentation, attain out by means of the Liquid Developer Telegram channel.
Please assist us debug! Keep these particulars in thoughts when reporting them:
- The txid you queried (if relevant)
- Whether you used REST or WebSocket
- The request you despatched and the response you acquired (together with error messages)
- Approximate timestamp with timezone
- Your integration context (e.g., swap move, service provider checkout) if related
To Learn More
- Check out the API reference
- Brush up on Liquid documentation
- Read about Liquid’s 2026 Roadmap
