Chapter 1: System Overview
What Capxul Is
Section titled “What Capxul Is”Capxul is a financial operations platform on stablecoin rails. Organizations manage treasury, pay teams, process invoices, and handle vendor payments — all in stablecoins (primarily USDC) via Safe multisig treasuries. Recipients receive funds into individual smart accounts and can route them to external wallets, bank accounts via off-ramp, mobile money, virtual cards, or other chains via bridging.
Every payment produces verifiable financial documentation. The platform closes the complete loop: from treasury funding through payment execution, recipient claiming, fiat conversion, and auditable record-keeping.
V2 migrates from Aragon-based infrastructure to Safe-based infrastructure with a new Convex backend. This is a ground-up redesign of the on-chain layer, the wallet infrastructure, the financial document system, and every integration point.
What V2 Does
Section titled “What V2 Does”The V2 platform supports the complete lifecycle of organizational financial operations:
-
Organizations create or connect a Safe treasury on Base, add employees via CSV upload, and fund salary streams. They approve invoices, pay vendors (in USDC or fiat), fund their treasury via fiat on-ramp, and monitor financial health through a live dashboard.
-
Employees receive salary via continuous USDC streams that accrue to their smart accounts. They claim funds on their own schedule, configure automatic routing (split between bank account, external wallet, virtual card, and other chains), and access payslips and claim receipts.
-
Vendors and contractors submit invoices through the platform, receive payments in USDC (or fiat via off-ramp), and track payment status in real time.
Every payment produces verifiable documentation. Every on-chain transaction links to an off-chain financial record via a bidirectional hash. The platform generates payslips, receipts, and invoices that serve as proof of compensation, proof of payment, and input for tax and compliance reporting.
Target Market
Section titled “Target Market”Capxul serves organizations that hold treasury in stablecoins and pay distributed teams, vendors, and contractors. The platform is designed for recipients who may or may not be crypto-native — the stablecoin infrastructure is invisible to end users. “Did I get paid?” and “Can I prove it?” are the questions that matter.
Launch Region
Section titled “Launch Region”Africa is the launch region — West Africa first, expanding across the continent as provider coverage enables new markets. A market is “launched” when at least one fiat ramp provider and one identity verification provider cover it behind the respective facades. Nigeria, Ghana, Kenya, and Uganda are the first configured markets — where Capxul is founded and where the first users operate. Other West African markets activate as provider coverage expands.
The architecture is jurisdiction-agnostic: fiat ramp providers, identity verification providers, and compliance thresholds are configured per-region via the facade pattern and multi-provider routing (see above). Expanding to new regions follows a phased plan:
- Africa (West Africa first) — the launch region
- Middle East + Latin America — second phase, likely served by different providers (e.g., Bridge for LatAm)
- Europe — third phase
Each phase requires adding providers behind the facades and configuring jurisdiction-specific compliance rules — not platform changes.
See Appendix B: Launch Region Configuration for jurisdiction-specific details (KYC thresholds, regulators, supported ID types, fiat providers) for the first configured markets.
Core Principles
Section titled “Core Principles”Pull-Based Architecture
Section titled “Pull-Based Architecture”All funds flow through the employee’s smart account.
Salary streams accrue to the smart account. Invoice payouts to vendors land in the vendor’s smart account. The smart account is the employee’s (or vendor’s) financial source of truth. Any downstream routing — send X% to an EOA, Y% to a bank via off-ramp, Z% to a virtual card, W% to another chain via bridge — is configured by the recipient in Convex and executed from the smart account.
Funds never skip the smart account and go directly to an external destination. That is how funds get lost. The smart account is the checkpoint between “payment was made” and “recipient chose what to do with it.”
Infrastructure Sovereignty
Section titled “Infrastructure Sovereignty”Every critical component that touches user funds or keys has a path to self-hosting or is on-chain and immutable:
- Smart account contracts (Openfort, GPL-3.0): on-chain, open source
- Key management (OpenSigner, MIT): self-hostable
- Recovery server (Shield): self-hostable, open source
- Safe modules (Payment Module, Zodiac Roles): on-chain, open source
- LlamaPay: on-chain, battle-tested since 2022
- Auth (Better Auth): self-hosted, open source
- Backend (Convex): Capxul-owned data
The one temporary dependency is Openfort’s hosted API, which wraps standard EVM operations and open-source contracts. It is replaceable with Convex actions + viem + permissionless.js on a defined timeline (see Phased Independence).
Facade Pattern
Section titled “Facade Pattern”External providers are abstracted behind interfaces. The application logic never calls a provider directly. It calls through a facade that selects the appropriate provider, normalizes formats, and tracks state in Convex.
Why Facades Exist
Section titled “Why Facades Exist”No single provider covers every market, every capability, and every price point. Providers cancel calls, change pricing, drop coverage, or get acquired. The facade makes this irrelevant to the platform. Adding, swapping, or deprecating a provider is a backend configuration change — no frontend code, no schema migrations, no user-facing disruption.
Capxul has four facades:
| Facade | What It Abstracts | Chapter |
|---|---|---|
| Fiat Ramp Facade | Off-ramp (crypto → fiat) and on-ramp (fiat → crypto) | Chapter 5 |
| Card Facade | Virtual card issuance and card-based spending | Card Facade |
| Bridge Facade | Cross-chain fund movement | Chapter 7 |
| Verification Facade | KYC (individual) and KYB (organization) identity checks | Chapter 11 |
Each facade follows the same pattern: a provider interface (what any provider must implement), a provider registry (which providers are active and where they operate), and Convex as the source of truth (the provider is never authoritative — Convex tracks state).
Provider Registry
Section titled “Provider Registry”Each facade has a provider registry table in Convex. The schema is consistent:
- Provider ID — unique identifier
- Type — what the provider does (e.g.,
off_ramp,on_ramp,bothfor fiat ramps;card_issuerfor cards) - Supported countries — which jurisdictions this provider operates in
- Supported capabilities — provider-specific (e.g.,
bank_transfer,mobile_money,apple_pay) - Active flag — can be disabled without removal
- Priority — when multiple providers cover the same country, priority determines the default
Multi-Provider Geographic Routing
Section titled “Multi-Provider Geographic Routing”When an operation is initiated, the facade selects a provider based on the user’s jurisdiction and the required capability. This is how Capxul serves multiple markets without depending on a single provider for all of them.
Concrete example — employee off-ramp:
An employee in Lagos initiates an off-ramp to their GTBank account. The fiat ramp facade:
- Reads the destination: Nigeria, NGN, bank transfer
- Queries
rampProvidersfor active providers supportingcountry: NG,capability: bank_transfer - Finds one provider (e.g., HoneyCoin). Selects it.
- Calls
createTransactionon the HoneyCoin adapter. Gets a deposit address. Session key sends USDC.
An employee in Mexico City initiates an off-ramp to their Banorte account. The same facade:
- Reads the destination: Mexico, MXN, bank transfer
- Queries
rampProvidersfor active providers supportingcountry: MX,capability: bank_transfer - Finds a different provider (e.g., Bridge). Selects it.
- Calls
createTransactionon the Bridge adapter. Same interface, different provider.
The frontend does not know which provider was selected. The session key logic does not change. The fiatTransactions record in Convex tracks the provider ID for reconciliation, but the UI shows the same experience regardless.
Multiple providers for the same country: If two providers both cover Nigeria, the facade selects by priority. Future enhancement: select by best quote (lowest fee) or by capability match (one provider handles bank transfers, another handles mobile money).
Fallback Behavior
Section titled “Fallback Behavior”- No provider covers the jurisdiction: The facade returns a clear error: “Off-ramp is not available in your region.” The UI handles this gracefully — the capability is hidden or grayed out.
- Provider is down: If a provider returns errors, the facade can fall back to the next-priority provider for that jurisdiction (if one exists). If no fallback, the transaction fails with a retryable error.
- Provider is deprecated: Set the active flag to
false. All new transactions route elsewhere. In-flight transactions complete on the deprecated provider (status tracking continues via webhooks and polling).
Adding a Provider
Section titled “Adding a Provider”Adding a new provider to any facade follows the same steps:
- Implement the facade interface. Write an adapter that translates between the facade’s standard interface and the provider’s API.
- Add a row to the provider registry. Specify supported countries, capabilities, and priority.
- Configure webhooks. The provider sends events to the facade’s webhook endpoint. The adapter parses provider-specific payloads into the standard format.
- Test in sandbox. Every facade supports a test mode that routes to the provider’s sandbox environment.
- Activate. Set the active flag to
true. New transactions for covered jurisdictions route to the new provider.
No platform code changes. No frontend changes. No schema migrations.
Master Architecture
Section titled “Master Architecture”Safe Treasury (Base) | |-- [Zodiac Roles Modifier] -- permissions layer | | | |-- [Payment Module] -- invoices, one-offs, off-ramp sends, bridge sends | | emits PaymentExecuted(safe, recipient, token, amount, docHash, paymentType) | | | |-- [LlamaPay] -- salary streaming (vanilla, no fork) | emits CreateStream, WithdrawFromStream | vEmployee Smart Account (Openfort ERC-4337) | |-- [Session Key] -- scoped: USDC contract + LlamaPay (on-chain) | destination enforcement in Convex (off-chain, Path A) | or via CapxulRouter contract (on-chain, Path B) | |-- Routes to: |-- External EOA (MetaMask, etc.) |-- Off-ramp provider deposit address (fiat ramp facade) |-- Card spend (card facade) |-- Bridge contract (bridge facade) |-- Stays in smart accountTwo Sides
Section titled “Two Sides”Org side (Safe treasury). A Safe on Base holds USDC. Custom modules and Zodiac infrastructure enable programmatic payment execution without manual multisig signing for every transaction. The Payment Module handles discrete payments. LlamaPay handles streaming payments. Zodiac Roles enforces permissions (spending limits, role-based access, backend service roles).
Employee side (Openfort smart account). Each employee has an ERC-4337 smart account via Openfort. Built-in session keys enable automated routing. The Convex backend orchestrates routing using session keys the employee has granted.
These two sides connect through LlamaPay (streaming) and the Payment Module (discrete payments). In both cases, funds move from the Safe to the employee’s smart account. Then the employee (or automated routing) moves funds outward.
System Layers
Section titled “System Layers”The V2 architecture is organized in layers. Each layer is documented in its own chapter:
| Layer | What It Does | Chapter |
|---|---|---|
| On-chain infrastructure | Safe, Payment Module, LlamaPay, Zodiac Roles | Chapter 2 |
| Smart account infrastructure | Openfort accounts, session keys, auth, recovery | Chapter 3 |
| Payments and streaming | LlamaPay streams, discrete payments, approval flows | Chapter 4 |
| Fiat ramps | Off-ramp (bank/MoMo), on-ramp (virtual accounts) | Chapter 5 |
| Card facade | Virtual card issuance, card spending, interchange | Chapter 6 |
| Cross-chain | Bridge facade, provider evaluation, multi-chain treasury | Chapter 7 |
| Financial documents | Invoices, payslips, receipts, on-chain anchoring | Chapter 8 |
| Event indexing | Custom indexer, Convex sync, treasury balance tracking | Chapter 9 |
| Dashboard and reporting | Treasury metrics, AP aging, scheduled reports | Chapter 10 |
| Identity verification | KYC/KYB via Shufti Pro, tiered verification | Chapter 11 |
| Independence plan | Phased decoupling from Openfort hosted API | Chapter 12 |
| Implementation roadmap | Unified build timeline across all layers | Chapter 13 |
| Open questions | Canonical list, organized by domain | Chapter 14 |
Technology Stack
Section titled “Technology Stack”| Component | Technology | Notes |
|---|---|---|
| Backend | Convex | Document database, real-time subscriptions, scheduled functions, HTTP actions |
| Auth | Better Auth + magic links | Separate Hono/Express server with SQLite (dev) or Turso/Postgres (prod) |
| Smart accounts | Openfort V1 (ERC-4337) | GPL-3.0 contracts, built-in session keys, guardian recovery |
| Key management | OpenSigner (Shamir 2-of-3) | MIT-licensed, self-hostable |
| Org treasury | Safe (multisig) | With Zodiac Roles Modifier |
| Streaming payments | LlamaPay (vanilla) | No fork, deployed on Base |
| Discrete payments | Custom Payment Module | Extends Zodiac Module.sol |
| Event indexing | Custom Node.js/TypeScript service | viem for chain interaction, hosted on Railway |
| Fiat ramp | HoneyCoin (at launch) | Provider abstraction supports future providers |
| Card issuer | Bridge (evaluating) | Behind card facade. See Appendix D |
| Bridge | deBridge (at launch) | Hyperbridge and LI.FI as future additions |
| Identity verification | Shufti Pro | KYC and KYB, tiered verification |
| Chain | Base (at launch) | Multi-chain via bridge and child Safes |
| Package manager | bun (JS/TS) |