Skip to main content

Non-custodial overview

OrcaRail is moving from a custodial sweep model (a server-held HD wallet per payment link, with funds swept and split after observation) to a non-custodial contract model (funds land in a per-link smart contract that splits atomically, and subscriptions pull from a payer-controlled allowance). This section is the reference home for the transition.

The narrative announcement is at /blog/non-custodial-roadmap. This page is the stable entry point; phase posts and docs pages link back here.

Who this affects

  • Merchants — your API surface does not change. Payment-link URLs, webhooks, and subscription objects keep their shape. What changes underneath is where funds live in transit.
  • Payers — one-off payments are identical. Subscriptions keep their one-time on-chain approve (EVM) or SPL delegate (Solana), but the spender becomes an auditable smart contract instead of an OrcaRail hot wallet.
  • Integrators — additive fields only (contract addresses, allowance metadata). Nothing existing is removed without a deprecation period.

Problem statement

In the current system, every payment link gets an HD-derived EOA or an Alchemy smart account. Deposits land there, then a keeper in api/src/withdrawals/ sweeps them and performs the merchant/platform/referral split. The keeper holds the key material (an encrypted mnemonic in hd_wallet_seed) and the in-flight funds.

That custody window is the problem. Eliminating it is a security win, a compliance simplification, and an operational one (no more sweep gas, no more mnemonic encryption key to protect).

Target state

  • EVM: PaymentLinkFactory computes a CREATE2 address per link; PaymentLinkReceiver clones accept funds and split atomically through FeeSplitter. Subscriptions run on SubscriptionHub with ERC-20 approve.
  • Solana: payment_link Anchor program owns a PDA per link; subscription program pulls via SPL delegate authority.
  • Bitcoin: 2-of-2 taproot multisig per link with a merchant signer and pre-signed refund PSBTs. BTC recurring is out of scope until Lightning BOLT12 matures.
  • Keeper: public charge() entrypoints; NestJS primary, Chainlink Automation or Gelato fallback; optional EigenLayer AVS if ever needed.

See Architecture for the full diagram.

Reading path

Phase status (summary)

The full phase list with status is at Roadmap. Quick index: