Skip to content

Chapter 1: System Overview

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.

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.

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.

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:

  1. Africa (West Africa first) — the launch region
  2. Middle East + Latin America — second phase, likely served by different providers (e.g., Bridge for LatAm)
  3. 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.

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.”

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).

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.

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:

FacadeWhat It AbstractsChapter
Fiat Ramp FacadeOff-ramp (crypto → fiat) and on-ramp (fiat → crypto)Chapter 5
Card FacadeVirtual card issuance and card-based spendingCard Facade
Bridge FacadeCross-chain fund movementChapter 7
Verification FacadeKYC (individual) and KYB (organization) identity checksChapter 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).

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, both for fiat ramps; card_issuer for 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

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:

  1. Reads the destination: Nigeria, NGN, bank transfer
  2. Queries rampProviders for active providers supporting country: NG, capability: bank_transfer
  3. Finds one provider (e.g., HoneyCoin). Selects it.
  4. Calls createTransaction on 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:

  1. Reads the destination: Mexico, MXN, bank transfer
  2. Queries rampProviders for active providers supporting country: MX, capability: bank_transfer
  3. Finds a different provider (e.g., Bridge). Selects it.
  4. Calls createTransaction on 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).

  • 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 new provider to any facade follows the same steps:

  1. Implement the facade interface. Write an adapter that translates between the facade’s standard interface and the provider’s API.
  2. Add a row to the provider registry. Specify supported countries, capabilities, and priority.
  3. Configure webhooks. The provider sends events to the facade’s webhook endpoint. The adapter parses provider-specific payloads into the standard format.
  4. Test in sandbox. Every facade supports a test mode that routes to the provider’s sandbox environment.
  5. 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.

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
|
v
Employee 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 account

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.

The V2 architecture is organized in layers. Each layer is documented in its own chapter:

LayerWhat It DoesChapter
On-chain infrastructureSafe, Payment Module, LlamaPay, Zodiac RolesChapter 2
Smart account infrastructureOpenfort accounts, session keys, auth, recoveryChapter 3
Payments and streamingLlamaPay streams, discrete payments, approval flowsChapter 4
Fiat rampsOff-ramp (bank/MoMo), on-ramp (virtual accounts)Chapter 5
Card facadeVirtual card issuance, card spending, interchangeChapter 6
Cross-chainBridge facade, provider evaluation, multi-chain treasuryChapter 7
Financial documentsInvoices, payslips, receipts, on-chain anchoringChapter 8
Event indexingCustom indexer, Convex sync, treasury balance trackingChapter 9
Dashboard and reportingTreasury metrics, AP aging, scheduled reportsChapter 10
Identity verificationKYC/KYB via Shufti Pro, tiered verificationChapter 11
Independence planPhased decoupling from Openfort hosted APIChapter 12
Implementation roadmapUnified build timeline across all layersChapter 13
Open questionsCanonical list, organized by domainChapter 14
ComponentTechnologyNotes
BackendConvexDocument database, real-time subscriptions, scheduled functions, HTTP actions
AuthBetter Auth + magic linksSeparate Hono/Express server with SQLite (dev) or Turso/Postgres (prod)
Smart accountsOpenfort V1 (ERC-4337)GPL-3.0 contracts, built-in session keys, guardian recovery
Key managementOpenSigner (Shamir 2-of-3)MIT-licensed, self-hostable
Org treasurySafe (multisig)With Zodiac Roles Modifier
Streaming paymentsLlamaPay (vanilla)No fork, deployed on Base
Discrete paymentsCustom Payment ModuleExtends Zodiac Module.sol
Event indexingCustom Node.js/TypeScript serviceviem for chain interaction, hosted on Railway
Fiat rampHoneyCoin (at launch)Provider abstraction supports future providers
Card issuerBridge (evaluating)Behind card facade. See Appendix D
BridgedeBridge (at launch)Hyperbridge and LI.FI as future additions
Identity verificationShufti ProKYC and KYB, tiered verification
ChainBase (at launch)Multi-chain via bridge and child Safes
Package managerbun (JS/TS)