StellarStream is a basic payment-streaming MVP for the Stellar ecosystem.
It includes:
- A React dashboard to create and monitor streams
- A Node.js/Express API for stream lifecycle operations
- A Soroban smart contract scaffold for on-chain stream logic
- A backlog folder with implementation task drafts
This repository is intentionally lightweight and easy to extend.
StellarStream models a payment stream where a sender allocates a total amount over a fixed duration.
As time passes, the recipient "vests" value continuously.
Current MVP behavior:
- Create stream
- List streams with live progress
- Cancel stream
- Show computed metrics (active/completed/vested)
- Track and display event history for stream lifecycle actions
Frontend (frontend, port 3000)
- React + Vite app
- Uses
/apiproxy to call backend - Polls stream list every 5 seconds
Backend (backend, port 3001)
- Express REST API
- SQLite database for persistent storage
- Event indexer worker for tracking stream lifecycle
- Computes progress in real time from timestamps
Contract (contracts)
- Soroban contract scaffold in Rust
- Supports
create_stream,claimable,claim, andcancel - Not yet integrated with backend runtime in this MVP
For each stream:
totalAmountstartAtdurationSecondsend = startAt + durationSeconds
At time t:
elapsed = clamp(t - startAt, 0, durationSeconds)ratio = elapsed / durationSecondsvested = totalAmount * ratioremaining = totalAmount - vested
Status rules:
scheduledwhent < startAtactivewhenstartAt <= t < endcompletedwhent >= endcanceledwhen stream was canceled
Base URL:
- Local:
http://localhost:3001 - Frontend proxy:
/api
Purpose:
- Service health check
Response:
service,status,timestamp
Purpose:
- List streams sorted by newest first, with optional filtering and pagination
Query params (optional):
status: scheduled | active | completed | canceledsender: string(exact sender match)recipient: string(exact recipient match)page: number(integer>= 1)limit: number(integer1..100)
Pagination behavior:
- If both
pageandlimitare omitted, legacy mode applies and all matching rows are returned. - If either
pageorlimitis provided, pagination mode applies with defaultspage=1andlimit=20.
Validation:
- Invalid
status,page, orlimitreturns400.
Response:
data: Stream[](includes computedprogress)total: number(filtered count before pagination)page: number(applied page)limit: number(applied page size)
Purpose:
- Fetch single stream by ID
Response:
data: Stream
Error:
404if stream does not exist
Purpose:
- Create a new stream
Request JSON:
sender: stringrecipient: stringassetCode: stringtotalAmount: numberdurationSeconds: number(minimum 60)startAt?: number(unix seconds)
Validation:
- Sender/recipient must be non-trivial strings
- Asset length must be 2..12
- Amount must be positive
- Duration must be at least 60 seconds
Response:
201withdata: Stream
Purpose:
- Cancel an existing stream
Response:
data: Streamwith canceled state
Error:
404if stream does not exist
Purpose:
- Returns implementation backlog items shown in UI
Response:
data: OpenIssue[]
Purpose:
- Fetch event history timeline for a specific stream
Response:
data: StreamEvent[](ordered by timestamp ascending)
Event types:
created: Stream was createdclaimed: Tokens were claimed from the streamcanceled: Stream was canceledstart_time_updated: Start time was modified
Each event includes:
id: Event IDstreamId: Associated stream IDeventType: Type of eventtimestamp: Unix timestamp when event occurredactor: Account that triggered the event (optional)amount: Amount involved (optional, for created/claimed)metadata: Additional context (optional)
Contract file:
contracts/src/lib.rs
Data:
NextStreamIdStream(stream_id) -> Stream
Implemented methods:
create_stream(...) -> u64get_stream(stream_id) -> Streamclaimable(stream_id, at_time) -> i128claim(stream_id, recipient, amount) -> i128cancel(stream_id, sender)
Important note:
claimcurrently updates accounting only.- Token transfer wiring is planned as next implementation step.
Prerequisites:
- Node.js 18+
- npm 9+
- Optional for contract work: Rust + Soroban toolchain
From repo root:
npm run install:all
npm run dev:backend
npm run dev:frontendManual alternative:
cd backend && npm install && npm run dev
cd frontend && npm install && npm run devOpen:
- Frontend:
http://localhost:3000 - Backend:
http://localhost:3001
Build:
npm run buildDeploy the Soroban contract to Stellar testnet.
- soroban-cli installed
- Rust toolchain with
wasm32-unknown-unknowntarget - Stellar testnet account with secret key
Set the SECRET_KEY environment variable and run:
SECRET_KEY="S..." npm run deploy:contractOr use the script directly:
SECRET_KEY="S..." ./scripts/deploy.shThe script will:
- Build the contract
- Deploy to Stellar testnet
- Output the contract ID
- Save the contract ID to
contracts/contract_id.txt
Required:
SECRET_KEY- Stellar account secret key for deployment (must have testnet XLM for fees)
Optional:
NETWORK_PASSPHRASE- Network passphrase (defaults to testnet:"Test SDF Network ; September 2015")RPC_URL- RPC endpoint URL (defaults tohttps://soroban-testnet.stellar.org:443)
- Copy the contract ID from the output or
contracts/contract_id.txt - Set
CONTRACT_IDin your backend.envfile - Ensure
SERVER_PRIVATE_KEYis set in your backend.envfile - Restart your backend service
Backend:
PORT(optional, defaults to3001)CONTRACT_ID(required for on-chain operations) - Contract ID from deploymentSERVER_PRIVATE_KEY(required for on-chain operations) - Stellar account secret keyRPC_URL(optional, defaults tohttps://soroban-testnet.stellar.org:443) - Soroban RPC endpointNETWORK_PASSPHRASE(optional, defaults to testnet) - Network passphraseALLOWED_ASSETS(optional, defaults toUSDC,XLM) - Comma-separated list of allowed asset codesDB_PATH(optional, defaults tobackend/data/streams.db) - SQLite database file path
Frontend:
VITE_API_URL(optional, defaults to/api)
Ignored files:
node_modules,dist, logs, local env files, Soroban build outputs
Root:
.gitignore: ignore rules for Node/Rust/local files.package.json: root helper scripts (install/build/dev delegates).README.md: project documentation.
GitHub templates:
.github/ISSUE_TEMPLATE/config.yml: issue template behavior..github/ISSUE_TEMPLATE/project-task.md: reusable issue template file.
Backend:
backend/package.json: backend dependencies and scripts.backend/tsconfig.json: backend TypeScript compiler config.backend/src/index.ts: API server, route handlers, request validation.backend/src/services/streamStore.ts: stream store + progress math + Soroban integration.backend/src/services/db.ts: SQLite database initialization and schema.backend/src/services/eventHistory.ts: event recording and retrieval functions.backend/src/services/indexer.ts: background worker for indexing contract events.backend/src/services/auth.ts: authentication middleware and JWT handling.backend/src/services/openIssues.ts: backlog entries returned by API.
Frontend:
frontend/index.html: Vite HTML entry.frontend/package.json: frontend dependencies and scripts.frontend/postcss.config.js: PostCSS plugin config.frontend/tailwind.config.js: Tailwind config (kept for styling extension).frontend/tsconfig.json: frontend TypeScript config.frontend/tsconfig.node.json: TS config for Vite/node-side files.frontend/vite.config.ts: dev server config + backend API proxy.frontend/src/main.tsx: React app bootstrap.frontend/src/App.tsx: top-level layout, polling, metrics, handlers.frontend/src/index.css: app styles.frontend/src/services/api.ts: typed API client functions.frontend/src/types/stream.ts: shared frontend data types.frontend/src/components/CreateStreamForm.tsx: stream creation form.frontend/src/components/StreamsTable.tsx: stream list and cancel actions.frontend/src/components/StreamTimeline.tsx: event history timeline display.frontend/src/components/IssueBacklog.tsx: backlog panel renderer.
Contract:
contracts/Cargo.toml: Rust crate and Soroban dependency config.contracts/src/lib.rs: Soroban contract implementation scaffold.
- Contract is not fully connected to backend execution path yet.
- Wallet sign/transaction flow is not active yet in UI.
- No authentication layer on write endpoints.
- Test coverage and CI can be expanded.
- Event indexer polls every 10 seconds (configurable).
- Move stream source of truth from memory to Soroban state.
- Add wallet-authenticated transaction signing flow.
- Add contract tests and backend integration tests.
- Enhance event history with claim events from contract.
- Add real-time event notifications via WebSockets.