Convert Stellar stablecoins (USDC / USDT) to fiat currencies and receive funds directly in your bank account — non-custodial, real-time, global.
- Overview
- Architecture
- Offramp Flow
- Tech Stack
- Setup Guide
- Environment Variables
- API Reference
- Troubleshooting
- Contributing
- Contact
- License
Stellar-Spend is a production-grade off-ramp application that lets users convert Stellar-based stablecoins to local fiat currencies (NGN, KES, GHS, etc.) with direct bank transfers. It bridges Stellar → Base via Allbridge, then routes the Base USDC to a Paycrest payout order that settles to the beneficiary's bank account.
Full-resolution SVG:
public/architecture.svg
The diagram shows the complete data flow:
- User signs a Soroban XDR in their Stellar wallet (Freighter / Lobstr)
- Next.js API builds the bridge transaction and submits it to Stellar
- Allbridge detects the Stellar deposit and releases USDC on Base
- Server creates a Paycrest payout order and sends Base USDC to the settlement address
- Paycrest converts USDC → fiat and initiates the bank transfer
- Beneficiary receives local currency (NGN, KES, GHS, …)
- Connect Freighter or Lobstr wallet (auto-detect)
- Real-time FX rate display (live USDC/NGN ticker)
- Dual input mode: enter crypto amount or fiat amount
- Automatic fee calculation (XLM or USDC gas fee)
- Non-custodial: the server never holds user funds
- Transaction history stored in browser
localStorage - PWA-installable on mobile
graph LR
A([User / Browser]) -->|1. Signs XDR| B[Stellar Network]
B -->|2. Bridge transfer| C[Allbridge Protocol]
C -->|3. USDC on Base| D[Base Chain]
D -->|4. Server sends USDC| E[Paycrest API]
E -->|5. Fiat settlement| F([Beneficiary Bank])
subgraph "Stellar-Spend Server"
G[Next.js API Routes]
G --> D
G --> E
end
A -->|Quote / Build TX| G
B -->|TX hash| G
Data flow summary:
| Step | Actor | Action |
|---|---|---|
| 1 | Browser | Fetches quote, builds Soroban XDR, user signs in wallet |
| 2 | Stellar | Signed transaction submitted; Allbridge bridge contract invoked |
| 3 | Allbridge | Detects Stellar deposit, releases USDC on Base |
| 4 | Server | Polls bridge status; sends Base USDC to Paycrest settlement address |
| 5 | Paycrest | Converts USDC → fiat, initiates bank transfer |
| 6 | Bank | Beneficiary receives local currency |
sequenceDiagram
participant U as User
participant App as Browser App
participant API as Next.js API
participant Stellar as Stellar Network
participant Bridge as Allbridge
participant Base as Base Chain
participant PC as Paycrest
U->>App: Enter amount + bank details
App->>API: POST /api/offramp/quote
API-->>App: { rate, destinationAmount, fees }
App->>API: POST /api/offramp/bridge/build-tx
API-->>App: { xdr }
App->>U: Prompt wallet signature
U->>App: Signed XDR
App->>API: POST /api/offramp/bridge/submit-soroban
API->>Stellar: Submit signed transaction
Stellar-->>Bridge: Bridge contract triggered
App->>API: GET /api/offramp/bridge/status/:txHash (poll)
Bridge-->>Base: USDC released on Base
API->>PC: POST /api/offramp/paycrest/order (create payout)
API->>Base: Send USDC to settlement address
App->>API: GET /api/offramp/status/:orderId (poll)
PC-->>U: Bank transfer settled
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 15.5 | App framework (App Router, API routes) |
| React | 19.0 | UI library |
| TypeScript | 5.7 | Type safety |
| Tailwind CSS | 4.2 | Styling |
| @stellar/stellar-sdk | 14.6 | Stellar / Soroban transaction building |
| @stellar/freighter-api | 6.0 | Freighter wallet integration |
| @allbridge/bridge-core-sdk | 3.29 | Stellar → Base bridge |
| viem | 2.47 | Base chain interaction |
| Paycrest API | v1 | Fiat payout / bank settlement |
| Sentry | 10.46 | Error monitoring |
| Vitest | 4.1 | Unit testing |
| Playwright | 1.58 | E2E testing |
- Node.js ≥ 20
- A Paycrest account (API key + webhook secret)
- A Base wallet private key (for the server-side payout wallet)
- A Base RPC URL (e.g. from Alchemy or Infura)
git clone https://github.com/whiteghost0001/Stellar-Spend.git
cd Stellar-Spendnpm installcp .env.example .env.localThen fill in .env.local — see Environment Variables below.
npm run devOpen http://localhost:3001.
npm test # unit tests (vitest)
npm run test:e2e # end-to-end tests (playwright, requires running server)npm run build
npm startnpm run build:analyzeAll variables are documented in .env.example. The table below summarises each one.
| Variable | Required | Exposed to browser | Description |
|---|---|---|---|
PAYCREST_API_KEY |
✅ | ❌ | Paycrest dashboard API key |
PAYCREST_WEBHOOK_SECRET |
✅ | ❌ | Paycrest webhook HMAC signing secret |
BASE_PRIVATE_KEY |
✅ | ❌ | Private key of the Base payout wallet (hex, 0x…) |
BASE_RETURN_ADDRESS |
✅ | ❌ | Base address for returns / treasury routing |
BASE_RPC_URL |
✅ | ❌ | Base chain RPC provider URL |
STELLAR_SOROBAN_RPC_URL |
✅ | ❌ | Soroban RPC endpoint (server-side) |
STELLAR_HORIZON_URL |
✅ | ❌ | Horizon endpoint (server-side) |
NEXT_PUBLIC_STELLAR_SOROBAN_RPC_URL |
✅ | ✅ | Soroban RPC endpoint (browser-safe) |
NEXT_PUBLIC_BASE_RETURN_ADDRESS |
✅ | ✅ | Base return address (browser-safe) |
NEXT_PUBLIC_STELLAR_USDC_ISSUER |
✅ | ✅ | Stellar USDC issuer account (for trustline filtering) |
⚠️ Never prefix secrets withNEXT_PUBLIC_. The app validates this at startup and throws if a secret is accidentally exposed.
| Method | Path | Description |
|---|---|---|
POST |
/api/offramp/quote |
Get a conversion quote with FX rate and fees |
GET |
/api/offramp/currencies |
List supported fiat currencies |
GET |
/api/offramp/institutions/[currency] |
List banks / institutions for a currency |
POST |
/api/offramp/verify-account |
Verify a beneficiary account number |
GET |
/api/offramp/rate |
Get live USDC/NGN spot rate |
| Method | Path | Description |
|---|---|---|
POST |
/api/offramp/bridge/build-tx |
Build Soroban XDR for the bridge transfer |
POST |
/api/offramp/bridge/submit-soroban |
Submit a signed Soroban XDR |
GET |
/api/offramp/bridge/status/[txHash] |
Poll Allbridge transfer status |
GET |
/api/offramp/bridge/tx-status/[hash] |
Poll Stellar on-chain transaction status |
GET |
/api/offramp/bridge/gas-fee-options |
Get available gas fee options (XLM / USDC) |
| Method | Path | Description |
|---|---|---|
POST |
/api/offramp/paycrest/order |
Create a Paycrest payout order |
GET |
/api/offramp/status/[orderId] |
Poll payout order status |
POST |
/api/offramp/execute-payout |
Trigger Base USDC transfer to Paycrest |
| Method | Path | Description |
|---|---|---|
POST |
/api/webhooks/paycrest |
Receive Paycrest webhook events (HMAC-verified) |
GET |
/api/health |
Health check endpoint |
Request
POST /api/offramp/quote
Content-Type: application/json
{
"amount": "100",
"currency": "NGN",
"feeMethod": "USDC"
}Response
{
"destinationAmount": "158202.00",
"rate": 1598,
"currency": "NGN",
"bridgeFee": "0.5",
"payoutFee": "0",
"estimatedTime": 300
}Request
POST /api/offramp/bridge/build-tx
Content-Type: application/json
{
"amount": "99.5",
"fromAddress": "GCFX...ABCD",
"toAddress": "0xd8dA...6045",
"feePaymentMethod": "stablecoin"
}Response
{
"xdr": "AAAAAgAAAAB...",
"sourceToken": { "symbol": "USDC", "decimals": 7, "chain": "STELLAR" },
"destinationToken": { "symbol": "USDC", "decimals": 6, "chain": "BASE" }
}One or more required env vars are missing. Copy .env.example to .env.local and fill in all values.
Install the Freighter browser extension, or use Lobstr as a fallback.
Open Freighter → Settings → Network → select Mainnet (Public).
Your Stellar account's XLM balance would fall below the minimum reserve after paying the gas fee. Either add more XLM or switch to USDC fee payment.
The Allbridge SDK could not fetch chain details. This is usually a transient network issue — retry after a few seconds.
The Paycrest rate API is unreachable. Check Paycrest status and retry.
Your USDC balance is insufficient to cover the transfer amount plus fees.
The CI build fails if .next/ exceeds 150 MB. Run npm run build:analyze to identify large chunks and consider dynamic imports.
Please read CONTRIBUTING.md for branch naming conventions, commit message format, and the pull request process.
Questions or feedback? Reach out on Telegram: t.me/Xoulomon
MIT © Stellar-Spend Contributors