Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

171 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Oxidity Wallet

Oxidity Wallet

Self-custody crypto wallet for Android, Chrome, and the open multi-chain web.

Website · Google Play · Chrome Web Store · Quick Start · Security

Google Play Chrome Web Store CI Security Policy License

Built with Rust, TypeScript, React, Capacitor, and a focus on secure multi-chain wallet UX.


Contents


What is Oxidity Wallet?

Oxidity Wallet is a self-custodial, multi-chain crypto wallet built as a monorepo.

It ships across multiple surfaces from the same core wallet codebase:

Surface Status Location
Android app Released apps/wallet/android
Browser extension Released apps/wallet
Web wallet / PWA Released apps/wallet
Marketing site Released apps/site
Rust backend API Production crates/api
Market price API Production oxidity-price

Private keys are created, encrypted, and used client-side. The backend provides chain data, transaction preparation, swap and bridge routing, price data, activity indexing, and operational APIs. It does not custody user funds.

This repository is designed to be:

  • Publicly auditable
  • Contributor-friendly
  • Reproducible across local and CI builds
  • Clear about security boundaries
  • Practical for real wallet development, not only demo usage

Security warning: this is wallet software. Development builds can move real funds if connected to real keys and real networks. Use throwaway wallets and test funds when developing, testing, or reviewing changes.


Repository layout

oxidity-wallet/
├── Cargo.toml
├── Cargo.lock
├── package.json
├── package-lock.json
├── VERSION
├── CHANGELOG.md
├── LICENSE
├── NOTICE
├── README.md
│
├── apps/
│   ├── wallet/                    # React wallet app, browser extension, Android shell
│   │   ├── src/
│   │   ├── tests/
│   │   ├── android/
│   │   ├── scripts/
│   │   ├── vite.config.ts
│   │   └── playwright.config.ts
│   │
│   └── site/                      # Marketing site and public docs pages
│       ├── src/
│       └── vite.config.ts
│
├── crates/
│   ├── api/                       # Rust backend API
│   │   ├── src/
│   │   └── migrations/
│   │
│   └── core/                      # Shared Rust domain/common crate
│       └── src/
│
├── data/
│   ├── global_data.json           # Chain, token, RPC, feature, and asset registry
│   ├── chains/                    # Chain/native asset artwork
│   ├── tokens/                    # Token artwork
│   └── generated/                 # Generated registry reports
│
├── oxidity-price/                 # Market price and OHLC API
│
├── deploy/
│   ├── nginx/                     # nginx templates and render scripts
│   ├── cloudflared/               # Cloudflare Tunnel service files
│   ├── systemd/                   # systemd service templates
│   └── rebuild-deploy.sh          # Build and deployment pipeline
│
├── scripts/
│   ├── build/
│   ├── release/
│   └── dev/
│
└── .github/
    ├── workflows/
    └── dependabot.yml

The wallet app, site, backend, deployment assets, generated registry data, and release tooling live together so security fixes and chain updates can land consistently across every delivery surface.


Supported platforms

Platform Package / target Notes
Android io.oxidity.wallet Capacitor shell around the wallet frontend
Chrome Extension Chrome Web Store Browser-extension package generated from apps/wallet
Web PWA wallet.oxidity.app Same wallet UI deployed as a web app
Marketing site oxidity.app Public landing site, docs, legal pages, support pages
Backend API 127.0.0.1:9555 in production behind nginx Rust Axum service
Price API 127.0.0.1:8787 in production behind nginx Market price and OHLC service

Supported blockchains

The source of truth is data/global_data.json.

Oxidity supports EVM and non-EVM chains through a shared registry model. Chain entries define RPC endpoints, feature flags, explorer links, wrapped-native assets, derivation paths, icons, default tokens, and wallet capabilities.

Examples of supported chains include:

  • Monero
  • Ethereum
  • BNB Smart Chain
  • Polygon
  • Base
  • Avalanche C-Chain
  • Optimism
  • Arbitrum One
  • Solana
  • Cardano
  • Bitcoin
  • XRP Ledger
  • Polkadot
  • Cosmos Hub
  • TRON
  • Sei
  • Litecoin
  • Dogecoin
  • Fraxtal
  • NEAR Protocol
  • Ethereum Classic
  • Bitcoin Cash
  • Unichain
  • Ethereum Sepolia
  • Avalanche Fuji C-Chain
  • BNB Smart Chain Testnet

Each chain can independently advertise capabilities such as:

  • Portfolio
  • Activity
  • Send
  • Receive
  • Swap
  • Bridge
  • Buy
  • NFT
  • Stake
  • WalletConnect

When adding or changing chain support, update the registry and run the registry validation scripts before opening a pull request.


Quick start

Backend

cargo run

The backend binds to 127.0.0.1:9555 by default.

Wallet frontend

cd apps/wallet
npm install --legacy-peer-deps
npm run dev

The wallet dev server runs on port 3000.

Marketing site

cd apps/site
npm install --legacy-peer-deps
npm run dev

The site dev server runs on port 3001.

Core readiness check

scripts/dev/public-readiness.sh

For full setup, extension packaging, Android builds, and local environment details, see CONTRIBUTING.md.


Technology stack

Backend

Technology Purpose
Rust Backend API and core services
Tokio Async runtime
Axum HTTP server and routing
Tower HTTP Middleware, CORS, headers
SQLx SQLite database access and migrations
Alloy Ethereum JSON-RPC, ABI, and transaction primitives
Reqwest Outbound HTTP clients
Serde JSON serialization
Tracing Structured logging
DashMap Shared concurrent state
Thiserror / Anyhow Error handling
bitcoin / k256 / ed25519-dalek / bech32 / bs58 / sha2 / blake2 / ripemd Multi-chain crypto primitives

Wallet frontend

Technology Purpose
React UI framework
Vite Build tool and dev server
TypeScript Static typing
Tailwind CSS Styling
Motion UI animations
Zustand Global wallet state
Ethers EVM wallet, signing, encoding
Solana Web3.js Solana support
Polkadot API / Keyring Polkadot support
XRPL libraries XRP Ledger support
CosmJS Cosmos support
monero-ts Web/PWA Monero key and wallet runtime
Reown WalletKit / WalletConnect WalletConnect v2
Capacitor Android bridge
Capacitor Secure Storage Native secure storage
Capacitor Biometric Auth Native biometric unlock
Stripe JS Onramp integration
Playwright End-to-end tests
Vitest Unit tests

Site frontend

The marketing site uses React, Vite, TypeScript, Tailwind CSS, React Router, Motion, and Stripe JS.

Infrastructure

Tool Purpose
nginx Reverse proxy, TLS-facing routing, static file serving, security headers
systemd Backend process supervision
Cloudflare Tunnel Public ingress without exposing origin ports directly
GitHub Actions CI, checks, and release workflows
Gradle Android release builds
Dependabot Dependency update automation

Architecture

Oxidity is split into three main layers:

Wallet UI
React, Zustand, Capacitor, Extension runtime
        |
        | HTTPS /api/*
        |
Rust backend
Axum, SQLx, Alloy, registry, quote/swap/send preparation
        |
        | RPC / HTTP integrations
        |
External services
RPC providers, explorers, Stripe, market-data providers, WalletConnect relay

Private-key operations remain client-side. The backend prepares and validates operations, but does not store seed phrases, private keys, or decrypted signing material.


Wallet frontend

The wallet app lives in apps/wallet.

It is shared by:

  • Web wallet
  • Android app
  • Browser extension

The app uses a flat view stack managed through Zustand instead of maintaining separate routers for each surface. This keeps navigation predictable across browser, Android, extension popup, and PWA contexts.

Main view areas

View Purpose
Splash Startup and initialization
Welcome New user entry
Create wallet Generate a new wallet
Import wallet Import mnemonic or private key
Walkthrough Onboarding flow
Main Portfolio, tabs, activity, and actions
Lock screen PIN and biometric unlock
Buy Stripe Onramp
Token management Add, hide, and manage assets
Token details Chart, balance, activity, and actions
Send Send flow
Bridge Cross-chain bridge
Stake Multi-chain staking
WalletConnect dApp sessions
Extension request Browser-extension approvals
Notifications Notification settings
Receive Receive address display
Receive QR QR receive screen
Address book Saved recipients
Add wallet Additional accounts
Transaction details Activity details
Advanced settings Developer and debug options
Legal Terms and privacy
Licenses Open-source license attribution
Support Help and feedback

State management

Global wallet state lives in apps/wallet/src/store/appStore.ts.

It tracks:

  • Vault and lock state
  • Active account
  • Portfolio balances
  • Chain catalog
  • Token registry
  • Activity history
  • Current view stack
  • Theme and fiat preferences
  • WalletConnect state
  • Notification preferences
  • Experience mode

App-wide state belongs in the store. Pure business logic belongs in lib/. Reusable UI primitives belong in components/.

Key management

Wallet secrets are never stored in plaintext.

The wallet vault flow:

  1. A mnemonic or private key is created or imported client-side.
  2. The secret is encrypted with AES-256-GCM.
  3. The encryption key is derived using PBKDF2 with a random salt.
  4. The encrypted vault payload is persisted.
  5. On Android, secure storage and biometric unlock can be backed by native platform APIs.
  6. Native signing paths can keep decrypted signing material out of the JavaScript thread after setup.

Development warning: never use a real seed phrase or private key in local builds, test builds, browser devtools, screenshots, logs, or issue reports.

Address derivation

Address derivation is isolated in apps/wallet/src/lib/chainAddresses.ts.

Chain family Derivation model
EVM Standard BIP-44 EVM derivation through Ethers
Solana Ed25519 derivation
Bitcoin Native SegWit derivation
TRON EVM-compatible key encoded with TRON address format
XRP Ledger XRPL keypair and address codec
Polkadot Substrate-compatible keyring
Cosmos BIP-44 Cosmos derivation and bech32 encoding

WalletConnect

WalletConnect v2 support is implemented in apps/wallet/src/features/walletconnect.

The service handles:

  • Session proposals
  • Sign requests
  • EVM action preparation
  • Request queues
  • Deep links
  • App links
  • Session policies
  • Approval UI handoff

WalletConnect approvals create per-origin policies that define allowed methods, expiry windows, and limits for supported value-bearing requests.

Browser extension

The extension runtime lives in apps/wallet/src/features/extension.

The extension injects an EVM-compatible provider and routes dApp requests into the wallet approval UI.

Supported request classes include:

  • eth_requestAccounts
  • eth_sendTransaction
  • eth_signTransaction
  • personal_sign
  • eth_sign
  • eth_signTypedData_v4

Approval flows must preserve clear user intent and must not sign or broadcast from stale, orphaned, duplicated, or background-restored requests.

Send safety

Send safety is handled through layered client-side checks.

Module Purpose
addressRisk.ts Detects burn addresses, self-sends, poisoning-like addresses, and malformed inputs
preflightChecks.ts Checks chain-specific requirements such as memos, tags, reserves, and fee risk
transactionSimulation.ts Builds a human-readable transaction summary before confirmation

Warnings should be explicit, understandable, and visible before the user confirms the action.

Staking

Staking support lives in apps/wallet/src/lib/staking.ts and apps/wallet/src/views/StakeView.tsx.

Current staking models include:

Protocol Chain Type
Lido Ethereum Liquid staking
Native delegation Solana Validator delegation
Native delegation Cosmos Validator delegation
Nomination Polkadot Validator nomination

Accessibility

Accessibility helpers live in apps/wallet/src/lib/accessibility.ts.

The wallet should respect:

  • Screen-reader announcements
  • Reduced-motion preference
  • High-contrast mode
  • Clear focus states
  • Tap targets suitable for mobile use

Backend API

The backend lives in crates/api.

It is a Rust Axum service responsible for:

  • App bootstrap data
  • Network status
  • Token catalog access
  • Portfolio reads
  • Price changes
  • Swap preparation
  • Bridge preparation
  • Send preparation
  • Signed transaction broadcast
  • NFT lookups
  • WalletConnect EVM preparation
  • Monero node status and companion routes
  • Reward eligibility and claim handling
  • Activity history
  • Telemetry middleware for opted-in clients

The backend defaults to:

127.0.0.1:9555

Backend state

The main AppState contains:

  • SQLite pool
  • Shared outbound HTTP client
  • Global settings
  • API key configuration
  • Token catalog index
  • Lazy EVM runtimes
  • Runtime initialization locks
  • Prepared swaps
  • Prepared bridges
  • Reward rate-limit state
  • Network-health cache
  • Price-change cache
  • Price-history cache

API routes

All API routes are mounted under /api.

Method Path Purpose
GET /api/health Liveness probe
GET /api/bootstrap App bootstrap metadata
GET /api/networks Enabled networks and health snapshot
GET /api/fiat/rates Fiat conversion rates
GET /api/catalog Chain and token catalog
POST /api/wallet/address Derive chain address for a wallet
GET /api/market/price-changes Cached 24h market changes
POST /api/market/track-token Track token price history
GET /api/market/noki NOKI market dashboard
GET /api/market/noki/{endpoint} NOKI market sub-endpoint
GET /api/image-proxy Proxied remote token and NFT images
POST /api/portfolio Balances and fiat values
POST /api/onramp/session Stripe Onramp session
POST /api/google/oauth/exchange Google OAuth code exchange
POST /api/token/resolve Token lookup
POST /api/token/details Token details and chart data
POST /api/nft/details NFT details
POST /api/nft/marketplace/collections NFT collection search
POST /api/nft/marketplace/collection NFT collection details
POST /api/quote-preview Fast swap quote preview
POST /api/swap/prepare Prepare swap
POST /api/swap/execute Execute prepared swap
POST /api/bridge/quote Bridge quote
POST /api/bridge/prepare Prepare bridge
POST /api/bridge/execute Execute prepared bridge
POST /api/walletconnect/evm/prepare Prepare WalletConnect EVM action
POST /api/stake/prepare Prepare staking transaction
POST /api/send/prepare Prepare unsigned send transaction
POST /api/send/broadcast Broadcast signed send transaction
POST /api/activity Wallet activity
POST /api/nft/send/prepare Prepare NFT transfer
POST /api/rewards/eligibility Reward eligibility
POST /api/rewards/claim Reward claim
GET /api/rewards/claim/{claim_id} Reward claim status
GET /api/rewards/ops Reward operations summary
POST /api/ai/chat Assistant endpoint
GET /api/monitor/stats Operational monitor statistics
GET /api/monero/status Monero daemon/wallet-RPC status
POST /api/monero/scan/register Monero view-key scan registration
GET /api/monero/scan/state Monero scan progress
POST /api/monero/tx/construct Monero unsigned txset construction
POST /api/monero/tx/relay Monero signed txset relay

Background workers

The backend starts long-running workers for:

  • Reward claim processing
  • Network-health refresh
  • Price-history sampling

Workers should be started from the backend boot path and should use shared application state rather than ad-hoc globals.

Price feed

The backend price feed uses a layered provider model with short-lived caching.

Typical provider order:

  1. Chainlink
  2. CoinGecko
  3. CoinMarketCap
  4. CryptoCompare
  5. Binance
  6. Etherscan
  7. Fallback aggregators

Cached prices may be used during temporary provider failures.

Swap and bridge preparation

Swap and bridge flows follow a two-phase model:

  1. Prepare on backend
  2. Client reviews and signs
  3. Backend validates and executes or broadcasts

This prevents the frontend from assembling high-risk transaction data blindly while still keeping signing client-side.


Market price API

The market price service lives in oxidity-price.

It provides market data and OHLC-style endpoints used by the wallet and site.

cd oxidity-price
python3 oxidity_price_api_ohlc_wallet_rpc.py

Security and cache helper tests:

python3 -m unittest test_price_api_security -v

The price API should remain defensive around:

  • Provider failures
  • Cache poisoning
  • Untrusted symbols
  • Rate limits
  • Stale responses
  • Unexpected upstream payloads

Security model

Oxidity is self-custodial wallet software. Security boundaries must stay clear.

Core principles

  • The backend does not custody private keys.
  • Seed phrases and private keys must never be logged.
  • Signing happens client-side or through native signing paths.
  • Development must use throwaway wallets and test funds.
  • The backend should validate signed transactions before broadcast when possible.
  • Approval prompts must be explicit and resistant to stale state.
  • dApp sessions must be scoped, reviewable, and revocable.
  • Sensitive configuration belongs in environment variables or secret stores, not in Git.

Wallet security

  • AES-256-GCM is used for encrypted vault storage.
  • PBKDF2-derived keys are used for vault encryption.
  • Android secure storage and biometric unlock can protect local unlock material.
  • Native signing can reduce key exposure to JavaScript on Android.
  • Send flows include address-risk and preflight checks.
  • WalletConnect approvals use per-origin session policies.

Backend security

  • The backend validates transaction structure and signer expectations where possible.
  • Protected RPCs can be used for MEV-sensitive sends.
  • Reward claims are rate-limited.
  • Telemetry is opt-in and handled through middleware.
  • SQLite migrations are managed through SQLx.
  • nginx applies security headers.
  • systemd service hardening is used in production.
  • Cloudflare Tunnel can provide public ingress without directly exposing origin services.

Responsible disclosure

Do not open public issues for vulnerabilities.

Report security issues using SECURITY.md.


Configuration

Backend environment variables

See .env.example and deploy/systemd/wallet-backend.env.example.

Variable Purpose
OXIDITY_WALLET_BACKEND_DB SQLite database path
OXIDITY_WALLET_BACKEND_BIND Backend bind address
OXIDITY_WALLET_BACKEND_PORT Backend HTTP port
WALLET_BACKEND_ADMIN_TOKEN Optional admin bearer token
HTTP_PROVIDER_<CHAIN_ID> Per-chain HTTP RPC override
PROTECTED_HTTP_PROVIDER_<CHAIN_ID> Per-chain protected RPC override
WEBSOCKET_PROVIDER_<CHAIN_ID> Per-chain WebSocket RPC override
COINGECKO_API_KEY CoinGecko API key
ETHERSCAN_API_KEY Etherscan API key
BINANCE_API_KEY Binance market-data API key
OPENSEA_API_KEY OpenSea API key
TATUM_API_KEY Tatum RPC gateway API key
COINMARKETCAP_API_KEY CoinMarketCap API key
CRYPTOCOMPARE_API_KEY CryptoCompare API key
NOKI_URL NOKI/price API base URL override
MASSIVE_API_KEY Fallback market-data API key
STRIPE_SECRET_KEY Stripe secret key
STRIPE_PUBLISHABLE_KEY Stripe publishable key
LIDO_REWARDS_ADDRESS Optional Ethereum mainnet Lido referral address; empty disables it
OAUTH_CLIENT_SECRET Google OAuth client secret
GOOGLE_DRIVE_CLIENT_ID Google Drive OAuth client ID
GOOGLE_DRIVE_REDIRECT_URI Google Drive OAuth redirect URI
MONERO_DAEMON_URL Optional Monero daemon URL for backend status/companion checks
MONERO_DAEMON_RPC_LOGIN_FILE Optional daemon RPC user:password file
MONERO_DAEMON_RPC_LOGIN Optional daemon RPC inline user:password
MONERO_WALLET_RPC_URL Optional local Monero wallet-RPC URL
MONERO_WALLET_RPC_LOGIN_FILE Optional wallet-RPC user:password file
MONERO_WALLET_RPC_LOGIN Optional wallet-RPC inline user:password
MONERO_WALLET_RPC_SEND_ENABLED Enables backend wallet-RPC send paths when set intentionally
OXIDITY_MONERO_MANIFEST Optional Monero launch manifest override
RUST_LOG Rust log level
CHAINS Optional enabled chain list
MAX_GAS_PRICE_GWEI Optional gas safety cap

Frontend environment variables

Defined in the wallet build environment; see .env.example for the tracked template.

Variable Purpose
VITE_WALLET_API_BASE_URL Primary backend API base URL
VITE_WALLET_API_BASE_URLS Optional comma-separated fallback API URLs
VITE_OXIDITY_PRICE_API_BASE_URL Wallet/site price API base URL override
VITE_REOWN_PROJECT_ID WalletConnect / Reown project ID
VITE_GOOGLE_DRIVE_CLIENT_ID Google Drive backup OAuth client ID
VITE_GOOGLE_DRIVE_REDIRECT_URI Optional Google Drive backup redirect URI
VITE_MONERO_DAEMON_RPC_URL Monero daemon base URL for web/native client sends

Local Monero runtime

Monero uses two local endpoints with different responsibilities:

  • VITE_MONERO_DAEMON_RPC_URL points the web/PWA and Android native Monero engines at a Monero daemon. Use a daemon base URL such as http://127.0.0.1:18081; do not point it at monero-wallet-rpc.
  • MONERO_WALLET_RPC_URL is an optional backend companion/helper endpoint for wallet-RPC subaddress, portfolio, and gated backend wallet-RPC send paths.

The expected daemon RPC is:

127.0.0.1:18081

Start the Oxidity wallet RPC helper (run from the repository root):

npm run monero:wallet-rpc

Then configure:

VITE_MONERO_DAEMON_RPC_URL=http://127.0.0.1:18081
MONERO_WALLET_RPC_URL=http://127.0.0.1:18083/json_rpc

Only enable backend wallet-RPC sends after the daemon and wallet are synced and the backend is intentionally allowed to submit sends from that opened wallet:

MONERO_WALLET_RPC_SEND_ENABLED=1

Android native Monero sends use the Molly engine and the daemon endpoint; they do not use host monero-wallet-rpc. See docs/monero.md.


Build, lint, and test commands

Rust backend

cargo check --locked
cargo test --locked
cargo build --release
cargo run

Wallet frontend

cd apps/wallet

npm install --legacy-peer-deps
npm run dev
npm run build
npm run lint
npm run test:unit
npm run test:e2e
npm run build:extension
npm run build:android

Site frontend

cd apps/site

npm install --legacy-peer-deps
npm run dev
npm run build
npm run lint

Registry validation

Run from the repository root:

npm run validate:registry

Price API

cd oxidity-price

python3 oxidity_price_api_ohlc_wallet_rpc.py
python3 -m unittest test_price_api_security -v

Public readiness gate

scripts/dev/public-readiness.sh

CI

The main workflow is .github/workflows/ci.yml.

Typical CI coverage includes:

Job Checks
Rust cargo fmt, cargo check, cargo clippy, cargo test
Wallet npm ci --legacy-peer-deps, npm run lint, npm run test:unit, npm run build
Site npm ci --legacy-peer-deps, npm run lint, npm run build
Extension npm ci --legacy-peer-deps, npm run build:extension, bundle secret check
Market API Python compileall, python -m unittest test_price_api_security -v

Pull requests should pass CI before review.


Coding conventions

Rust

  • Use clear module boundaries.
  • Keep public errors typed with thiserror.
  • Prefer Result<T, AppError> or API-specific error wrappers.
  • Use #[serde(rename_all = "camelCase")] for JSON-facing structs.
  • Keep Solidity ABI bindings in Rust source via sol! macros where practical.
  • Avoid raw environment lookups scattered through handlers.
  • Add migrations for schema changes.
  • Keep source headers aligned with the project license.

TypeScript and React

  • Keep app-wide state in Zustand.
  • Keep pure logic in lib/.
  • Keep reusable UI in components/.
  • Keep full-screen screens in views/.
  • Avoid unnecessary any.
  • Respect strict TypeScript.
  • Use platform gates for native-only functionality.
  • Keep chain-specific logic isolated.
  • Add tests for new pure-logic modules.
  • Keep approval, signing, and send flows boring, explicit, and hard to misuse.

UX expectations

Wallet UX must be calm, obvious, and defensive.

Important flows should handle:

  • Back navigation
  • App switching
  • Reloads
  • Popup closes
  • Background restarts
  • Network failures
  • Duplicate taps
  • Slow RPC responses
  • Stale approval state
  • Locked wallet state
  • Interrupted signing flows

A crypto wallet should not assume users behave gently. They do not.


Adding a new chain

  1. Add the chain to data/global_data.json.
  2. Add chain artwork under data/chains/ if needed.
  3. Add token artwork under data/tokens/ if needed.
  4. Add EVM constants only when needed by Rust code.
  5. Add address derivation support for non-EVM chains.
  6. Wire send, receive, swap, bridge, NFT, or staking support only where the chain actually supports it.
  7. Run registry validation.
  8. Add tests for chain-specific parsing, address handling, and transaction preparation where relevant.

Run from the repository root:

npm run validate:registry

Do not mark a feature as supported in the registry until the app flow is actually usable.


Adding a new API endpoint

  1. Define request and response types.
  2. Implement the Axum handler.
  3. Register the route.
  4. Add client support in apps/wallet/src/lib/api.ts.
  5. Add tests.
  6. Document configuration or operational requirements.
  7. Avoid adding new telemetry routes unless the existing telemetry middleware cannot support the use case.

Handlers should be explicit about validation, failure modes, and user-facing error messages.


Deployment

Production deployment is designed around a hardened Debian host with nginx, systemd, Cloudflare Tunnel, and local services bound to loopback.

Main deployment pieces:

Path Purpose
deploy/bootstrap-fresh-debian.sh One-time host bootstrap
deploy/install-host-runtime.sh Runtime asset installation
deploy/rebuild-deploy.sh Build, deploy, restart, and verify
deploy/nginx/ nginx templates
deploy/systemd/ systemd unit templates
deploy/cloudflared/ Cloudflare Tunnel service files

Common deployment command:

./deploy/rebuild-deploy.sh

Useful deployment options:

./deploy/rebuild-deploy.sh --build-only
./deploy/rebuild-deploy.sh --skip-android

Health checks should include:

  • Local backend health
  • Local backend bootstrap
  • Host-routed nginx bootstrap
  • Marketing site root
  • Wallet app root
  • /.well-known/assetlinks.json
  • Extension package availability
  • Public HTTPS checks after Cloudflare Tunnel settles

Contributing

Contributions are welcome.

Start here:

Before opening a pull request:

cargo test --locked
npm run validate:registry
scripts/dev/public-readiness.sh

For frontend changes, also run the relevant workspace checks:

cd apps/wallet
npm run lint
npm run test:unit

For site changes:

cd apps/site
npm run lint
npm run build

Security-sensitive changes should be small, reviewable, and clearly explained.


Versioning and releases

VERSION is the canonical semantic version for the main project.

It is used for:

  • Backend versioning
  • Wallet app versioning
  • Marketing site versioning
  • Android versionName
  • Derived Android versionCode (MAJOR * 10000 + MINOR * 100 + PATCH)
  • Runtime version constants

The Chrome extension version can advance independently through apps/wallet/package.json when browser-store release timing requires it.

Release notes live in CHANGELOG.md, including a Play-publisher XML-style block that mirrors Google Play localized release notes (language BCP-47 tags) and includes store country metadata.

Releases are tagged in Git and published through the relevant distribution channels after default-branch release preparation is complete.


Acknowledgements

Oxidity depends on a large open-source ecosystem across Rust, TypeScript, cryptography, wallet infrastructure, chain clients, and developer tooling.

Thanks to the maintainers and contributors whose work makes secure wallet development possible.


License

Oxidity Wallet source code is licensed under the Apache License 2.0.

See:

You may view, audit, fork, copy, modify, build, and use the code, including commercially, under the terms of Apache-2.0.

Trademark and brand

The Apache-2.0 license covers the source code.

It does not grant rights to impersonate or confusingly reuse the Oxidity name, logo, icon, screenshots, promotional graphics, app identity, or brand assets.

Public forks must rename and rebrand before distribution.

See TRADEMARKS.md.

Releases

Sponsor this project

Packages

Used by

Contributors

Languages