Skip to main content

Architecture Overview

How all the pieces of Rayos fit together β€” explained from the ground up.


The Big Picture​

Rayos is not one app β€” it is a platform made of 7 working repositories. Each one does a specific job, like instruments in an orchestra. Alone they are useful. Together they make something remarkable.

Here is the full system at a glance:

flowchart TB
subgraph Users["User Devices"]
WEB["web-dashboard\nNext.js"]
MOB["mobile-app\nReact Native / Expo"]
DEMO["demo-app\nNext.js"]
end

subgraph SDK["wallet-sdk (TypeScript NPM Package)"]
PASS["Passkey Module"]
CONT["Contract Client"]
RC["Relay Client"]
SESS["Session Manager"]
end

subgraph BACK["relay-backend (NestJS on Render)"]
WA["WebAuthn Controller"]
RLY["Relay Controller"]
SESS2["Sessions Controller"]
REC["Recovery Controller"]
IDX["Indexer"]
end

subgraph CHAIN["wallet-contracts (Rust / Soroban)"]
WALLET["Wallet Contract\nidentity and auth"]
POLICY["Policy Contract\nrules and limits"]
FACTORY["Factory Contract\ndeployment"]
end

STELLAR["Stellar Blockchain"]

WEB --> SDK
MOB --> SDK
DEMO --> SDK
SDK --> BACK
BACK --> STELLAR
CHAIN --> STELLAR

Layer by Layer​

Think of Rayos as having four layers, like a building:

+----------------------------------------------+
| Layer 4: User Interfaces |
| web-dashboard Β· mobile-app Β· demo-app |
+----------------------------------------------+
| Layer 3: SDK |
| @rayos/wallet-sdk |
+----------------------------------------------+
| Layer 2: Backend |
| relay-backend |
+----------------------------------------------+
| Layer 1: Smart Contracts |
| wallet-contracts (on Stellar Soroban) |
+----------------------------------------------+

Each layer only talks to the layer immediately below it. The UI never directly touches the blockchain β€” it goes through the SDK, which goes through the relay, which talks to Soroban.


Layer 1 β€” Smart Contracts​

Repository: wallet-contracts

This is the foundation. Three smart contracts written in Rust, running on Stellar Soroban.

graph LR
F["Factory Contract\ndeploy_wallet"] -->|creates| W
W["Wallet Contract\nverifies passkeys"] -->|checks rules| P
P["Policy Contract\nSpend Limits + Recovery"]
ContractJobAnalogy
FactoryDeploys new wallet contractsThe bank that opens new accounts
WalletVerifies passkey signatures, holds signersThe vault door
PolicyEnforces spend limits, sessions, guardiansThe vault rule book

Key Insight: These contracts run on-chain. Rayos (the company, the relay, anyone) cannot override them. The rules are math.


Layer 2 β€” Relay Backend​

Repository: relay-backend

A NestJS API that acts as a helpful middleman. It has 5 jobs:

  1. WebAuthn β€” Generate challenges for registration/login, verify passkey responses
  2. Relay β€” Wrap user transactions in a fee-bump (pays XLM gas so users don't have to)
  3. Sessions β€” Manage session keys for repeated low-risk operations
  4. Recovery β€” Orchestrate multi-step guardian recovery
  5. Indexer β€” Watch the chain for events (transaction history)

Trustless by design: The relay can pay your gas fee, but it cannot move your funds. If it tried to tamper with your signed transaction, the blockchain would reject it immediately.


Layer 3 β€” Wallet SDK​

Repository: wallet-sdk

A TypeScript npm package (@rayos/wallet-sdk) that every frontend app installs. It wraps all the complexity of passkeys, XDR signing, and relay calls into simple function calls:

// Create a new wallet
const { address } = await walletSdk.createWallet(options);

// Sign and submit a transaction
const receipt = await walletSdk.signAndSubmit(xdr, opts);

Apps never touch WebAuthn or Soroban directly. The SDK is the single abstraction layer.


Layer 4 β€” User Interfaces​

Three apps, all powered by the SDK:

AppRepoDescription
Web Dashboardweb-dashboardFull wallet management β€” balance, send, policies, guardians
Mobile Appmobile-appiOS + Android native experience with device biometrics
Demo Appdemo-appA merchant checkout demo β€” gasless payments in USDC

How a Transaction Flows​

Here is what happens when you tap "Send" β€” from your finger to the blockchain:

sequenceDiagram
participant U as User
participant APP as App
participant SDK as wallet-sdk
participant WA as WebAuthn Device
participant RELAY as relay-backend
participant STELLAR as Stellar

U->>APP: Tap "Send"
APP->>SDK: signAndSubmit(xdr)
SDK->>WA: Prompt biometric
WA-->>U: Show Face ID / Touch ID
U-->>WA: Scan fingerprint
WA-->>SDK: Passkey signature
SDK->>RELAY: Submit signed XDR
RELAY->>RELAY: Add fee-bump to pay gas
RELAY->>STELLAR: Submit to network
STELLAR-->>RELAY: Transaction hash
RELAY-->>SDK: hash and status
SDK-->>APP: SubmitResponse
APP-->>U: Receipt

The Infra Layer​

Repository: infra

This repo contains no running code β€” it is pure configuration and tooling:

  • Shared GitHub Actions workflows (used by every repo)
  • Environment variable templates
  • Docker Compose for local development
  • Deployment configs for Render and Vercel

Every other repo pulls its CI/CD from infra β€” change a workflow once, update everywhere.


Environments​

Rayos uses a four-tier environment model:

graph LR
LOCAL["local\nYour machine"] -->|promote| DEV
DEV["testnet-dev\nAuto on merge to main"] -->|promote| STAGING
STAGING["testnet-staging\nStable pre-release"] -->|promote| PROD
PROD["mainnet\nProduction coming soon"]
EnvironmentNetworkPurpose
localStellar TestnetYour own machine
testnet-devStellar TestnetShared staging, auto-deployed
testnet-stagingStellar TestnetStable, mirrors mainnet config
mainnetStellar MainnetProduction (pending audit)

No repo can skip directly to mainnet. The pipeline enforces the promotion order.


Further Reading​