Oxalway is a B2B freelancer payroll system that bridges traditional fiat payments with blockchain payouts. When a payer completes a fiat → crypto on-ramp checkout (simulated in test mode via Alchemy Pay, Transak, or MoonPay), the backend automatically prepares a USDC payout to a Stellar wallet via a Soroban smart contract.
The project is a monorepo with the following components:
- Rust API (
rust-backend/) - Axum-based web server handling on-ramp webhooks and payout orchestration - Soroban Contract (
soroban-contract/) - Stellar smart contract for processing and recording payroll payouts - React Dashboard (
artifacts/crypto-payroll-flow/) - Browser-local demo interface for payroll management - Python Integration (
rust-backend/scripts/invoke_payout.py) - Stellar SDK wrapper for transaction signing and submission - Shared Libraries (
lib/) - TypeScript libraries for API client, API spec, Zod schemas, and database utilities
- Rust and Cargo
- Node.js and pnpm
- Python 3.11+ with uv
- Stellar CLI (for contract deployment)
# Install dependencies
pnpm install
# Install Python dependencies
uv synccd rust-backend
cp .env.example .env # Configure environment variables
cargo runThe API starts at http://localhost:3001 with endpoints:
GET /healthz- Health checkPOST /webhook/onramp- Provider-agnostic on-ramp webhook handler (acceptsonramp.checkout.completed, plus legacycheckout.session.completed)POST /payroll/trigger- Manual payout trigger
pnpm --filter @workspace/crypto-payroll-flow run devThe dashboard runs in browser-local demo mode.
Configure these in rust-backend/.env:
# Server
PORT=3001
RUST_LOG=oxalway_api=debug,tower_http=info
# Stellar Configuration
STELLAR_NETWORK=testnet
SOROBAN_CONTRACT_ID=your_deployed_contract_id
TREASURY_SECRET_KEY=your_treasury_secret_key # NEVER commit this
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org # Optional
# Python
PYTHON_BIN=python3 # Optional, defaults to python3Security Note: Never commit TREASURY_SECRET_KEY. In production, store it in a secret manager and implement provider webhook signature verification before processing webhooks.
The contract provides three main functions:
initialize(admin: Address)- Sets the treasury admin (one-time setup)process_payout(admin, freelancer_address, amount, invoice_id)- Records a payout to persistent storageget_payout(invoice_id)- Retrieves payout records by invoice ID
cd soroban-contract
stellar contract build
stellar contract deploy \
--wasm target/wasm32v1-none/release/oxalway_payroll_contract.wasm \
--source-account treasury \
--network testnetAfter deployment, set the resulting contract ID in SOROBAN_CONTRACT_ID.
With the Rust API running:
curl -X POST http://localhost:3001/webhook/onramp \
-H 'Content-Type: application/json' \
-d '{
"type": "onramp.checkout.completed",
"data": {
"object": {
"amount_total": 1245000,
"currency": "usd",
"provider": "alchemy-pay",
"metadata": {
"freelancer_wallet": "GABCD1234EXAMPLESTELLARWALLET",
"invoice_id": "inv_oxalway_1001"
}
}
}
}'curl -X POST http://localhost:3001/payroll/trigger \
-H 'Content-Type: application/json' \
-d '{
"freelancer_wallet": "GABCD1234EXAMPLESTELLARWALLET",
"amount_usd": 12.45,
"invoice_id": "inv_oxalway_1001"
}'# Check TypeScript libraries
pnpm run typecheck:libs
# Full typecheck (includes artifacts and scripts)
pnpm run typecheckpnpm run build- A payer completes a simulated fiat → crypto on-ramp checkout (Alchemy Pay, Transak, or MoonPay test mode) with freelancer wallet and invoice ID in metadata
- The provider sends an
onramp.checkout.completedwebhook to the Rust API - The Rust API validates the webhook and extracts payment details
- The API calls the Python script to construct and sign a Soroban transaction
- The transaction invokes
process_payouton the deployed contract - The contract records the payout in persistent storage
- The transaction hash is returned and can be tracked on Stellar Testnet
In test mode the checkout is simulated in the dashboard (simulateOnRampCheckout in artifacts/crypto-payroll-flow/src/lib/onramp.ts); swapping in a real provider later means replacing that function with the provider's SDK while keeping the same return shape.
- Implement provider webhook signature verification
- Move treasury keys to a secret manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- Add proper error handling and retry logic for failed transactions
- Implement proper logging and monitoring
- Add rate limiting and authentication to API endpoints
- Conduct thorough security audits of the smart contract
- Consider multi-sig treasury for production deployments