0Bit Documentation

Fallback liquidity

How 0Pools handles unavailable pool liquidity and how partners should build fallback UX.

Fallback liquidity is what happens when the preferred pool path cannot safely fill a request. Partners should not depend on the internal fallback mechanism. They should build against public outcomes: unavailable quote, reservation conflict, pending trade, terminal status, and support ids.

Outcome model

Partner fallback choices

OutcomeGood product behavior
pool_dryOffer a later retry or another entitled pool.
engine_unavailableShow temporary unavailable state.
rate_unavailableAsk user to refresh later.
Reservation failedRequest a fresh quote; preserve support ids.
Trade failedFollow refund/support policy.
ReleasedLet user retry from quote step.

What not to do

  • Do not invent a different route in the browser.
  • Do not submit the same expired quote repeatedly.
  • Do not expose internal fallback provider names.
  • Do not credit users from an unavailable quote.
  • Do not turn unavailable responses into tight retry loops.

Before and after

Before 0PoolsWith 0Pools
Product team writes custom fallback route code.Product handles stable unavailable/status outcomes.
Internal provider outage leaks to user.User sees product-safe route unavailable state.
Retry can duplicate execution.Idempotent transact and quote freshness control retries.

Support packet

For fallback issues, provide pool id, quote id if any, request id, unavailable reason or error code, environment, amount, side, network, and timestamp.

Fallback UX matrix

User momentProduct should doProduct should not do
User has not accepted a quote yet.Ask for a fresh quote, reduce amount, or show another entitled pool.Hide the error and keep showing stale terms.
Firm quote expired.Refresh and require the user to accept new terms.Execute the expired quote id.
Quote unavailable.Show a temporary unavailable state with retry.Tell the user which private liquidity source failed.
Trade reserved for longer than expected.Keep funds pending and escalate with ids.Credit final balance early.
Trade failed/released.Follow refund/release policy and let user restart from quote.Retry execution blindly with the same expired quote.

Fallback decision tree

The tree keeps fallback decisions at the product-contract layer. It does not ask the partner to choose an internal provider, inspect reserve source, or run a treasury playbook.

Before 0Pools in fallback design

Without a shared pool abstraction, fallback often becomes a product engineering problem: code tries provider A, then provider B, then a manual desk, each with different status names and reconciliation exports. That creates duplicated executions, hidden stale prices, and support tickets that only engineering can resolve.

With 0Pools, fallback is represented as stable outcomes:

  • no quote
  • quote expired
  • reservation failed
  • trade pending
  • trade settled
  • trade failed
  • trade released or returned

Those outcomes are enough for a partner product to build a reliable UX while 0Bit operations handle the private liquidity layer.

Logging example

{
  "event": "pool_fallback_outcome",
  "pool_id": "EUR-USDT",
  "side": "on_ramp",
  "amount": "500.00",
  "reason": "pool_dry",
  "request_id": "req_abc",
  "user_message": "This route is unavailable right now."
}

Log unavailable reasons for analytics and support, but keep user copy generic and avoid private operating detail.

Fallback decision matrix

Fallback should protect the user from stale prices and unclear settlement states.

Failure pointSafe fallbackUnsafe fallback
Discovery unavailableHide action or show maintenance state.Show cached pool as available.
Indicative quote unavailableLet user retry later or change amount/network.Invent a price from last quote.
Firm quote expiredRequest fresh quote and confirmation.Execute old quote.
Transact timeoutRetry with same idempotency key.Create a new execution attempt blindly.
Trade stuck reservedKeep pending, poll status, alert support.Mark failed without terminal evidence.

Fallback log record

{
  "partner_order_id": "order_7841",
  "pool_id": "EUR-USDT",
  "failure_point": "firm_quote_expired",
  "user_action": "requested_new_quote",
  "previous_quote_id": "pq_live_01J4",
  "new_quote_required": true
}

Retry policy

Use short retries for transient reads, idempotent retries for transact uncertainty, and no automatic retry for expired quote acceptance. Anything that changes accepted economics requires user confirmation again.

Implementation depth

This page is about building clear fallback UX when liquidity is unavailable or delayed. For developers, the durable boundary is simple: your product should depend on unavailable reasons, retry policy, alternate enabled pools, and existing trade status; it should not depend on which liquidity source failed or recovered. That boundary is what lets 0Pools improve liquidity operations without forcing every partner to rebuild product code.

Product scenario

A pool returns available:false. The app offers a smaller amount, a different entitled lane, or a retry later instead of repeatedly forcing the same quote.

Before and after in practice

Before 0PoolsWith 0Pools
The product masks failures as generic errors and users retry until they create support noise.The product treats unavailable liquidity as a normal state with clear options and no hidden execution attempts.
Product teams infer liquidity behavior from provider-specific screens or manual notes.Product teams branch on 0Pools objects: pool, quote, trade, balance, webhook, and ledger.
Support asks engineering to reconstruct state from logs.Support starts from request id, quote id, trade id, event id, and ledger id.

System flow

Records to keep

RecordWhy it mattersExample
unavailable_reasonMachine branch for the fallback.rate_unavailable
attempt_countPrevents retry loops.2
alternate_pool_idAnother entitled lane if available.EUR-USDC
user_messageCopy shown to the user.This lane is temporarily unavailable.

A useful implementation stores these records before adding optional analytics. Analytics can be rebuilt from durable state; missing ids usually cannot be reconstructed after a customer-impacting failure.

Example product record

{
  "product_area": "fallback-liquidity-review",
  "partner_reference": "partner_order_123",
  "pool_id": "EUR-USDT",
  "quote_id": "pq_test_123",
  "transact_id": "pt_test_456",
  "status": "reserved",
  "request_id": "req_01HZY0POOLS",
  "reconciliation_state": "open"
}

This record is intentionally partner-facing. It references 0Pools objects and your own product ids, but it does not include private liquidity routes, treasury balances, raw provider payloads, or customer secrets.

Failure modes and recovery

Failure modeProduct response
Retry loopCap attempts and back off.
Silent route switchAsk user to confirm different terms or asset.
Existing reserved trade lostContinue status tracking for accepted quotes.
Private outage exposedUse product-safe unavailable language.

Use-case patterns

PatternHow 0Pools helps
Amount reductionLet user try smaller amount if limits allow.
Alternate stablecoinOffer another entitled asset.
Delayed retryNotify when the lane becomes available.

Developer checklist

  • Read runtime discovery and capabilities before rendering enabled actions.
  • Create firm quotes only when the user is ready to accept the terms.
  • Execute from your server with an idempotency key.
  • Treat webhooks and status reads as the source of truth for settlement state.
  • Reconcile by durable ids first, then by amount and timestamp.
  • Do not branch product behavior on provider names, route names, reserve balances, or treasury assumptions.

On this page