Liquidity safeguards
The 0Pools safeguards that keep headless liquidity flows bounded, auditable, and retry-safe.
0Pools is headless, so safeguards matter more than they do in a hosted widget. The API assumes the partner owns the UI and uses server-side controls to keep quote, execution, balance, and settlement behavior bounded.
Safeguard map
Main safeguards
| Safeguard | Protects against |
|---|---|
| Server-only secret keys | Browser-controlled execution. |
| Partner entitlement | Cross-tenant pool access. |
| Short quote TTL | Stale prices and long market-risk windows. |
| Single-use quote | Reusing old accepted terms. |
| Idempotency | Duplicate clicks and retry timeouts. |
| Prefunded balance gate | Delivering before funding exists. |
| Daily/velocity limits | Unexpected volume spikes. |
| Terminal statuses | Ambiguous ledger outcomes. |
| Request ids | Support investigation without secrets. |
Slippage and quote risk
0Pools reduces exposed slippage by making the acceptance window explicit: a firm quote is time-limited and single-use. That does not mean markets have no risk; it means the partner UX should not accept an expired or unavailable price.
Developer checklist
- Never execute from the browser.
- Disable accept when the firm quote expires.
- Send a stable
Idempotency-Key. - Treat unavailable quotes as normal.
- Persist the exact quote and trade ids.
- Update customer ledger only from terminal status.
- Alert on stuck
reservedtrades.
Anti-patterns
| Anti-pattern | Why it is unsafe |
|---|---|
| Keeping an accept button active after expiry. | User accepts a stale price. |
| Generating a new idempotency key on retry. | Duplicate execution risk. |
Crediting user balance on reserved. | Settlement may still fail or release. |
| Logging secret keys in support packets. | Credential exposure. |
| Showing internal provider states. | Leaks unstable operations. |
Safeguard lifecycle
Each step has a distinct safety job. Discovery prevents unauthorized pool use. Quote expiry limits stale-price acceptance. Idempotency prevents duplicate execution. Terminal status prevents premature final ledger updates.
Threat model for headless liquidity
| Risk | Safeguard | Developer obligation |
|---|---|---|
| Browser executes trades directly. | Server-only secret key. | Never expose secret keys or transact endpoints client-side. |
| User accepts stale price. | Firm quote expiry. | Enforce expiry in backend and UI. |
| Duplicate click creates duplicate trade. | Idempotency. | Reuse a stable idempotency key for the same acceptance. |
| Partner draws without funding. | Prefunded balance gate where enabled. | Check balance and block orders before final acceptance. |
| Settlement is uncertain. | Trade status and webhooks. | Keep user funds pending until terminal policy is satisfied. |
| Support cannot trace incident. | Request, quote, trade, event ids. | Store ids with your internal order. |
Before and after safeguards
| Without 0Pools-style controls | With 0Pools safeguards |
|---|---|
| Quote, execution, ledger, and support records are separate ad hoc systems. | Quote, trade, status, balance, and request ids follow one lifecycle. |
| A retry timeout can accidentally duplicate conversion. | Idempotency gives retry-safe execution. |
| Users may accept prices that are minutes old. | Firm quote expiry forces refresh. |
| Partner support needs private provider context. | Support can start from public ids and escalate privately. |
Production readiness questions
- Can a user accept after quote expiry?
- Can the browser see a secret key?
- Can two clicks create two trades?
- Can a pending trade credit final balance?
- Can support trace an order without private route information?
- Can finance match partner order, quote, trade, ledger, and webhook event?
Any "yes" to the first four or "no" to the last two should block launch.
Threat model and controls
Institutional integrations need explicit controls for money movement failure modes.
| Risk | Control | Test |
|---|---|---|
| Duplicate execution | Idempotency key per accepted quote. | Double-click accept and retry network timeout. |
| Stale price | Firm quote expiry and disabled accept. | Attempt transact after expiry. |
| Client-side secret leak | Server-only secret keys. | Inspect client bundle and mobile config. |
| Webhook replay | Signature verification and event dedupe. | Replay same event id. |
| Ledger drift | Append-only ledger joined to status. | Compare daily close to status feed. |
| Unsupported network | Discovery/capability validation. | Submit unsupported destination network. |
Webhook processing guard
async function processPoolEvent(event: PoolEvent) {
await verifySignature(event);
const inserted = await db.events.insertOnce(event.id, event);
if (!inserted) return;
const trade = await db.trades.findById(event.data.transactId);
await db.trades.updateStatus(trade.id, event.data.status);
if (event.data.status === 'settled') {
await ledger.postSettlement(trade.id, event.data.ledgerRef);
}
}Production readiness evidence
A partner should be able to show logs for idempotency retries, webhook signature verification, expired quote rejection, ledger posting, and support escalation using only partner-visible ids.
Implementation depth
This page is about understanding safeguards that bound headless liquidity flows. For developers, the durable boundary is simple: your product should depend on account gates, amount limits, quote expiry, idempotency, status, and reconciliation; it should not depend on risk thresholds, monitoring internals, and treasury controls. That boundary is what lets 0Pools improve liquidity operations without forcing every partner to rebuild product code.
Product scenario
A high-traffic app adds a buy button. Safeguards ensure the button cannot execute without entitlement, cannot reuse stale terms, cannot double-submit, and cannot mark final balance before terminal state.
Before and after in practice
| Before 0Pools | With 0Pools |
|---|---|
| The product trusts UI state and creates edge cases under refreshes, retries, and network errors. | Server-side gates and durable ids define the only valid path from quote to ledger. |
| 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
| Record | Why it matters | Example |
|---|---|---|
gate_result | Which access gate passed. | entitled |
quote_expires_at | Bounds price acceptance. | 2026-06-28T... |
idempotency_key | Dedupes writes. | order_123_accept_1 |
terminal_status | Drives ledger mutation. | settled |
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": "liquidity-safeguards",
"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 mode | Product response |
|---|---|
| Stale quote accepted | Reject and refresh quote. |
| Double-click execution | Return existing trade through idempotency. |
| Amount exceeds limit | Block before quote. |
| Webhook replay | Dedupe event ids. |
Use-case patterns
| Pattern | How 0Pools helps |
|---|---|
| Consumer apps | Protect against accidental duplicate purchases. |
| Enterprise treasury | Bound operational risk per transaction. |
| Support operations | Standardize failure handling. |
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.