Wallet and neobank swaps
How wallet and neobank partners can use 0Pools for approved fiat-to-stablecoin conversion flows.
Wallets and neobanks often want conversion inside their own UX: a user sees a balance, chooses an amount, reviews a quote, accepts, and expects the app ledger to update. 0Pools supports the liquidity part of that workflow for approved partners.
User experience model
Why 0Pools is useful here
| Wallet need | 0Pools primitive |
|---|---|
| Show only enabled assets. | Entitled pools and capabilities. |
| Avoid stale prices. | Short-lived firm quote. |
| Avoid duplicate conversion. | Idempotent transact. |
| Show pending state. | reserved trade. |
| Reconcile final balance. | Terminal status and ledger joins. |
Before and after
| Before 0Pools | With 0Pools |
|---|---|
| App has to run its own quote engine. | App calls 0Pools quote. |
| Conversion status is custom per rail. | App maps standard trade statuses. |
| Support asks engineering to trace provider logs. | Support starts with quote/trade/request ids. |
Ledger pattern
Do not update the user's available wallet balance until terminal conditions are met. You can show a pending balance while the trade is reserved.
{
"wallet_entry": "pending_conversion",
"pool_id": "EUR-USDT",
"quote_id": "pq_test_123",
"transact_id": "txn_test_456",
"status": "reserved"
}Product boundary
0Pools does not replace your wallet ledger, transaction history, fraud controls, or user support rules. It gives your backend an approved liquidity execution record.
Wallet architecture pattern
The wallet ledger should remain the source of truth for what the user can spend. 0Pools supplies the conversion record that justifies a pending row, an available-balance update, or a release.
Example use cases
| Use case | How 0Pools helps | Boundary |
|---|---|---|
| EUR balance to USDT wallet | Provides quote, expiry, execution, and status for the conversion. | Wallet controls user balance display and account permissions. |
| Stablecoin cash-in for neobank users | Lets backend route approved conversion through a common pool model. | Neobank controls account funding rules and disclosures. |
| Internal treasury-to-user wallet movement | Gives a recordable conversion primitive where approved. | Treasury policy and approval remain outside the partner integration contract. |
| Cross-border wallet funding | Can support approved corridors with quote and terminal state. | Country/corridor claims require product and compliance approval. |
Before 0Pools in wallet products
Without a shared pool layer, wallet teams often build several partial systems: one quote service, one provider adapter, one settlement watcher, one ledger mapper, and one support workflow per corridor. That works at low volume but becomes hard to reason about when quote expiry, network choice, settlement delay, and user balance updates all happen in different services.
With 0Pools, the wallet team can model the conversion as one product lifecycle:
- Check entitled pools.
- Quote the user request.
- Lock the quote for a short window.
- Execute once with idempotency.
- Create a pending wallet ledger row.
- Move the ledger row only from trusted status reads or signed events.
- Reconcile quote, trade, wallet entry, and report row.
Support view
Your support dashboard should show the user order and the pool record side by side:
{
"wallet_order_id": "swap_8421",
"user_visible_state": "pending",
"pool_id": "EUR-USDT",
"quote_id": "pool_quote_123",
"trade_id": "pool_trade_456",
"pool_status": "reserved",
"network": "tron",
"request_id": "req_abc"
}Support should not need route names, venue names, treasury accounts, or provider dashboards to explain the user's current state.
Native app swap contract
Wallet and neobank integrations need a clean separation between mobile UX and server execution.
| Layer | Responsibility |
|---|---|
| Mobile app | Collect amount, show quote, countdown, status, and receipt. |
| Partner backend | Authenticate user, request quote, transact, store ids, process webhooks. |
| 0Pools | Return entitled pools, quotes, trades, statuses, and ledger signals. |
| Partner ledger | Credit/debit user account based on terminal state. |
Mobile state mapping
| Backend state | Mobile label |
|---|---|
quote_active | Review quote. |
quote_expired | Quote expired. |
reserved | Processing. |
settled | Completed. |
failed | Could not complete. |
returned | Returned. |
Swap order example
{
"swap_order_id": "swap_7841",
"user_account_id": "user_acct_22",
"pool_id": "EUR-USDT",
"network": "polygon",
"quote_id": "pq_live_01J4",
"transact_id": "pt_live_9A2",
"mobile_state": "processing"
}Implementation depth
This page is about using 0Pools behind wallet and neobank conversion experiences. For developers, the durable boundary is simple: your product should depend on enabled lanes, quote terms, destination/network fields, and status timeline; it should not depend on source routing, inventory movements, and internal liquidity fallback. That boundary is what lets 0Pools improve liquidity operations without forcing every partner to rebuild product code.
Product scenario
A neobank adds a stablecoin tab. Users see a normal buy/sell experience, while the server handles entitlement, quote lock, idempotent execution, and ledger updates.
Before and after in practice
| Before 0Pools | With 0Pools |
|---|---|
| The wallet embeds multiple liquidity vendors and every vendor status leaks into the user experience. | The wallet uses one 0Pools lifecycle and maps it into simple pending, complete, failed, or returned states. |
| 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 |
|---|---|---|
wallet_user_id | Your internal user reference. | usr_123 |
destination_address | Locked on firm quote for delivery. | 0x... |
network | Selected chain/network. | arbitrum |
wallet_balance_entry | Your balance posting. | wb_456 |
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": "wallet-neobank-swaps",
"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 |
|---|---|
| Destination changed after quote | Require a new firm quote. |
| Vendor status exposed | Map to product status names. |
| Ledger posted from browser callback | Use server status/webhook only. |
| Unsupported wallet network | Validate before quote. |
Use-case patterns
| Pattern | How 0Pools helps |
|---|---|
| Neobank crypto tab | Buy stablecoin inside banking app. |
| Self-custody wallet | Top up external address. |
| Brokerage app | Offer stablecoin conversion with clear status. |
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.