βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER INTERFACE β
β (Frontend / API Client) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β HTTP/REST
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BACKEND API SERVER β
β (Express.js / Node) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β API Routes Layer β β
β β /api/v1/streams (streaming-routes.js) β β
β β - POST /streams Create stream β β
β β - POST /streams/:id/withdraw Withdraw funds β β
β β - DELETE /streams/:id Cancel stream β β
β β - GET /streams/:id Get details β β
β β - GET /streams/:id/balance Check balance β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Service Layer β β
β β streaming-service.js β β
β β - Transaction building β β
β β - Contract invocation β β
β β - Result parsing β β
β β - Transaction polling β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Database Layer β β
β β Stream.js (MongoDB Model) β β
β β - Stream metadata β β
β β - Status tracking β β
β β - Transaction history β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Soroban RPC
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SOROBAN RPC SERVER β
β (Stellar Network Node) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Contract Calls
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STREAMING PAYMENTS CONTRACT β
β (Soroban Smart Contract) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Contract Functions β β
β β β β
β β create_stream(sender, recipient, token, amount, ...) β β
β β ββ Validate parameters β β
β β ββ Calculate rate_per_ledger β β
β β ββ Transfer tokens to contract β β
β β ββ Store stream data β β
β β ββ Emit "created" event β β
β β β β
β β withdraw(stream_id, amount) β β
β β ββ Verify recipient authorization β β
β β ββ Calculate available balance β β
β β ββ Transfer tokens to recipient β β
β β ββ Update withdrawn amount β β
β β ββ Emit "withdraw" event β β
β β β β
β β cancel_stream(stream_id) β β
β β ββ Verify sender authorization β β
β β ββ Calculate recipient balance β β
β β ββ Transfer balance to recipient β β
β β ββ Calculate and refund unstreamed β β
β β ββ Remove stream from storage β β
β β ββ Emit "canceled" event β β
β β β β
β β balance_of(stream_id) -> i128 β β
β β ββ Get stream data β β
β β ββ Calculate elapsed ledgers β β
β β ββ Calculate streamed amount β β
β β ββ Return (streamed - withdrawn) β β
β β β β
β β get_stream(stream_id) -> Stream β β
β β ββ Return stream data from storage β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Storage Layer β β
β β β β
β β DataKey::Stream(stream_id) -> Stream { β β
β β sender: Address, β β
β β recipient: Address, β β
β β token: Address, β β
β β rate_per_ledger: i128, β β
β β start_ledger: u32, β β
β β stop_ledger: u32, β β
β β withdrawn: i128 β β
β β } β β
β β β β
β β DataKey::NextStreamId -> u64 β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Token Transfers
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TOKEN CONTRACT β
β (Soroban Token / SAC) β
β β
β - Holds streamed tokens β
β - Transfers on create_stream β
β - Transfers on withdraw β
β - Transfers on cancel_stream β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
User/Sender
β
β 1. POST /api/v1/streams
β {sender, recipient, token, amount, start, stop}
βΌ
Backend API
β
β 2. Validate input
β 3. Build transaction
βΌ
Streaming Contract
β
β 4. Validate parameters
β 5. Calculate rate_per_ledger = amount / (stop - start)
β 6. Call token.transfer(sender -> contract, amount)
βΌ
Token Contract
β
β 7. Transfer tokens
βββββ
β
β 8. Store stream data
β 9. Emit "created" event
βΌ
Backend API
β
β 10. Save to MongoDB
β 11. Return stream_id
βΌ
User/Sender
β
ββ Stream created! β
User/Recipient
β
β 1. POST /api/v1/streams/:id/withdraw
β {amount}
βΌ
Backend API
β
β 2. Validate input
β 3. Build transaction
βΌ
Streaming Contract
β
β 4. Verify recipient authorization
β 5. Calculate available = (rate Γ elapsed) - withdrawn
β 6. Validate amount <= available
β 7. Call token.transfer(contract -> recipient, amount)
βΌ
Token Contract
β
β 8. Transfer tokens
βββββ
β
β 9. Update withdrawn += amount
β 10. Emit "withdraw" event
βΌ
Backend API
β
β 11. Update MongoDB
β 12. Return success
βΌ
User/Recipient
β
ββ Tokens received! β
User/Sender
β
β 1. DELETE /api/v1/streams/:id
βΌ
Backend API
β
β 2. Build transaction
βΌ
Streaming Contract
β
β 3. Verify sender authorization
β 4. Calculate recipient_balance = streamed - withdrawn
β 5. Calculate refund = total - streamed
β
β 6. If recipient_balance > 0:
β Call token.transfer(contract -> recipient, recipient_balance)
βΌ
Token Contract
β
β 7. Transfer to recipient
βββββ
β
β 8. If refund > 0:
β Call token.transfer(contract -> sender, refund)
βΌ
Token Contract
β
β 9. Transfer refund to sender
βββββ
β
β 10. Remove stream from storage
β 11. Emit "canceled" event
βΌ
Backend API
β
β 12. Update MongoDB (status = canceled)
β 13. Return success
βΌ
User/Sender
β
ββ Stream canceled! Refund received! β
User/Anyone
β
β 1. GET /api/v1/streams/:id/balance
βΌ
Backend API
β
β 2. Build read transaction
βΌ
Streaming Contract
β
β 3. Get stream data
β 4. Get current ledger
β 5. Calculate elapsed = current - start
β 6. Calculate streamed = rate Γ elapsed
β 7. Calculate available = streamed - withdrawn
β 8. Return available
βΌ
Backend API
β
β 9. Return balance
βΌ
User/Anyone
β
ββ Balance: X tokens β
ββββββββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ
β β Frontend β Backend β Contract β Token β
ββββββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€
β Frontend β - β HTTP β - β - β
ββββββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€
β Backend β HTTP β - β RPC β - β
ββββββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€
β Contract β - β RPC β - β Invoke β
ββββββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€
β Token β - β - β Invoke β - β
ββββββββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PERSISTENT STORAGE (On-Chain) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Stream(0) -> { β
β sender: GABC..., β
β recipient: GDEF..., β
β token: CXYZ..., β
β rate_per_ledger: 10, β
β start_ledger: 1000, β
β stop_ledger: 2000, β
β withdrawn: 5000 β
β } β
β β
β Stream(1) -> { ... } β
β Stream(2) -> { ... } β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INSTANCE STORAGE (On-Chain) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β NextStreamId -> 3 β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MONGODB (Off-Chain) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β streams: [ β
β { β
β streamId: "0", β
β contractId: "C...", β
β sender: "GABC...", β
β recipient: "GDEF...", β
β tokenAddress: "CXYZ...", β
β totalAmount: "10000", β
β status: "active", β
β createdTxHash: "abc123...", β
β createdAt: "2025-01-15T10:00:00Z" β
β }, β
β ... β
β ] β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Contract Events Backend Processing
βββββββββββββββββ ββββββββββββββββββ
created(stream_id) ββββββ> Save to MongoDB
ββ sender Update status: active
ββ recipient Store tx hash
ββ total_amount Index by sender/recipient
withdraw(stream_id) ββββββ> Update MongoDB
ββ recipient Update withdrawn amount
ββ amount Log transaction
canceled(stream_id) ββββββ> Update MongoDB
ββ recipient_balance Update status: canceled
ββ refund_amount Store cancel tx hash
Archive stream
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER LAYER β
β - Wallet signature required β
β - Private key never leaves wallet β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API LAYER β
β - Input validation (express-validator) β
β - Rate limiting β
β - CORS protection β
β - HTTPS only β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CONTRACT LAYER β
β - Authorization checks (require_auth) β
β - Balance validation β
β - Parameter validation β
β - Integer overflow protection β
β - Atomic operations β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NETWORK LAYER β
β - Stellar consensus β
β - Transaction fees β
β - Ledger finality β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Development Testing Production
βββββββββββ βββββββ ββββββββββ
Local Testnet -> Stellar Testnet -> Stellar Mainnet
β β β
β β β
βΌ βΌ βΌ
Local MongoDB Test MongoDB Production MongoDB
β β β
β β β
βΌ βΌ βΌ
Local Backend Test Backend Production Backend
β β β
β β β
βΌ βΌ βΌ
Local Frontend Test Frontend Production Frontend
This architecture provides:
- β Clear separation of concerns
- β Scalable design
- β Security at every layer
- β Event-driven updates
- β Efficient data flow
- β Production-ready structure