Scalable, secure, and decentralized smart contracts for Soroban on Stellar.
Spin up a local Stellar node, deploy the contract, and seed it with test data in one command:
# Set the deployer key and seed keys, then start everything
export SOURCE_ACCOUNT=<your-local-secret-key>
export ADMIN_KEY=<admin-secret> ADMIN_ADDRESS=<admin-address>
export MERCHANT1_KEY=<m1-secret> MERCHANT1_ADDRESS=<m1-address>
export MERCHANT2_KEY=<m2-secret> MERCHANT2_ADDRESS=<m2-address>
export MERCHANT3_KEY=<m3-secret> MERCHANT3_ADDRESS=<m3-address>
export PAYER_KEY=<payer-secret> PAYER_ADDRESS=<payer-address>
export TOKEN_ADDRESS=<sac-token-address>
docker compose upThe setup service waits for the Stellar node to pass its health check, then
builds and deploys the contract, writes the CONTRACT_ID to a shared volume at
/shared/contract-id.txt, and seeds 3 merchants, 5 payments, and 2 refunds.
Generate local keys with:
stellar keys generate --network local alice
stellar keys address aliceFund them via the local Friendbot:
curl "http://localhost:8000/friendbot?addr=<address>"Tear everything down (including the shared volume) with:
docker compose down -vPre-built CLI binaries are published with every GitHub Release.
Linux (x86_64)
curl -fsSL https://github.com/Gloriachinedu/lumenflow-contracts/releases/latest/download/lumenflow-cli-v<VERSION>-x86_64-unknown-linux-gnu.tar.gz \
| tar -xz -C /usr/local/bin lumenflow-cliLinux (arm64)
curl -fsSL https://github.com/Gloriachinedu/lumenflow-contracts/releases/latest/download/lumenflow-cli-v<VERSION>-aarch64-unknown-linux-gnu.tar.gz \
| tar -xz -C /usr/local/bin lumenflow-climacOS (x86_64)
curl -fsSL https://github.com/Gloriachinedu/lumenflow-contracts/releases/latest/download/lumenflow-cli-v<VERSION>-x86_64-apple-darwin.tar.gz \
| tar -xz -C /usr/local/bin lumenflow-climacOS (Apple Silicon / arm64)
curl -fsSL https://github.com/Gloriachinedu/lumenflow-contracts/releases/latest/download/lumenflow-cli-v<VERSION>-aarch64-apple-darwin.tar.gz \
| tar -xz -C /usr/local/bin lumenflow-cliWindows (x86_64, PowerShell)
Invoke-WebRequest -Uri "https://github.com/Gloriachinedu/lumenflow-contracts/releases/latest/download/lumenflow-cli-v<VERSION>-x86_64-pc-windows-msvc.zip" -OutFile lumenflow-cli.zip
Expand-Archive lumenflow-cli.zip -DestinationPath $env:USERPROFILE\binReplace <VERSION> with the desired release tag (e.g. 1.0.0). Checksums for each archive are published as .sha256 files alongside the binaries on the release page.
Install from source
cargo install --path cli/lumenflow-cliLumenFlow is a production-grade payment processing smart contract for the Stellar Soroban network. It provides:
- Merchant management — registration, profiles, deactivation
- Payment processing — ed25519 signature-verified token transfers
- Refund lifecycle — initiate → approve/reject → execute
- Multi-signature payments — configurable threshold approvals
- Payment history queries — paginated, filtered, and sorted
- Admin controls — global stats, archiving, automated cleanup
- Full contract API reference (all functions, parameters, return types, errors):
docs/api-reference.md - Interactive API explorer for the public contract entrypoints:
docs/openapi.yaml - Architecture overview available in
docs/ARCHITECTURE.md - Audit plan and scope published in
docs/audit/audit-report.md - Refund lifecycle state diagram available in
docs/refund-lifecycle.md - Testing guidance available in
docs/testing-guide.md - Multisig payment flow guide available in
docs/multisig-guide.md - Contributor onboarding video script available in docs/onboarding-video-script.md
- Secrets and secure local environment setup in
docs/secrets-and-local-env.md - Payment link generator guide in
docs/payment-link-guide.md
stateDiagram-v2
[*] --> Pending
Pending --> Approved : merchant approves
Pending --> Rejected : merchant rejects
Approved --> Completed : merchant executes refund
Rejected --> [*]
This contract uses saturating accumulation for global payment and refund volumes to prevent runtime panics in release mode.
For interactive contract testing, load the OpenAPI file in Swagger UI or any compatible viewer. Soroban contract calls are authenticated through signed transactions rather than a bearer token, so each request should include the required signer and authorization context.
| Tool | Install |
|---|---|
| Rust (stable) | https://rustup.rs |
| Stellar CLI | https://developers.stellar.org/docs/tools/stellar-cli |
| Docker Desktop (local network) | https://www.docker.com/products/docker-desktop |
Verify:
rustc --version
cargo --version
stellar --version
docker --versionAdd the WASM target:
rustup target add wasm32-unknown-unknownlumenflow-contracts/
├── contracts/
│ ├── lumenflow/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs # Contract entry points
│ │ ├── types.rs # Data structures
│ │ ├── storage.rs # Persistent storage helpers
│ │ ├── error.rs # Typed error codes
│ │ ├── helper.rs # Auth & validation utilities
│ │ └── test.rs # Unit tests
│ └── router/ # Payment router contract
├── scripts/
│ ├── deploy.sh # Build + deploy helper
│ └── test.sh # Lint + test runner
├── cli/
│ └── lumenflow-cli/ # CLI tool and config loader
├── .github/
│ ├── workflows/
│ │ ├── ci.yml # Lint, test, WASM build
│ │ └── release.yml # Tag-triggered release
│ ├── ISSUE_TEMPLATE/
│ └── PULL_REQUEST_TEMPLATE.md
├── Cargo.toml # Workspace manifest
├── rust-toolchain.toml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
└── SECURITY.md
The lumenflow CLI provides quick access to common contract workflows such as payments, refunds, history queries, and admin statistics.
The CLI loads configuration from a .lumenflow.toml file by default, and environment variables override values from the file. The CLI also loads a .env file if present.
Example .lumenflow.toml:
network = "testnet"
contract_id = "GC..."
source_account = "S..."Supported environment variables:
LUMENFLOW_NETWORK— Stellar network (local,testnet,mainnet)LUMENFLOW_CONTRACT_ID— deployed contract IDLUMENFLOW_SOURCE— source account secret key used for CLI commands
You can also pass a custom config file path with --config.
lumenflow pay --merchant G... --amount 1000 --order_id ORDER_001lumenflow refund init --order_id ORDER_001 --amount 500lumenflow history --merchant G...lumenflow statsNew merchants can register through the following flow:
- Connect Wallet: Ensure your Stellar wallet is connected.
- Check Registration: Call
is_registered(address)to check if you already have a profile. - Register: Call
register_merchantwith your business details and category. - Verification: Upon success, you will be redirected to the dashboard where you can start accepting payments.
Existing profiles can be retrieved using get_merchant(address).
# From the workspace root
cargo build --target wasm32-unknown-unknown --release --package lumenflowThe compiled WASM is at:
target/wasm32-unknown-unknown/release/lumenflow.wasm
Current binary size: ~55 KB (well within Soroban's 128 KB contract size limit).
CI enforces a 100 KB threshold — the build fails if the WASM exceeds this size. To check locally:
wc -c target/wasm32-unknown-unknown/release/lumenflow.wasm# Run all tests
cargo test --all-features
# Run a specific test
cargo test test_successful_refund_flow
# Full lint + test pipeline
./scripts/test.sh
# Generate coverage report locally (requires cargo-llvm-cov)
COVERAGE=1 ./scripts/test.sh
# → writes lcov.info to the workspace rootCoverage threshold: 80% line coverage is enforced in CI. Install cargo-llvm-cov once with:
cargo install cargo-llvm-cov --lockedPerformance benchmarks for contract hot paths are available in contracts/lumenflow/benches/benchmark.rs and documented in docs/benchmarking.md.
cargo bench --manifest-path contracts/lumenflow/Cargo.tomlThe benchmark harness reports relative runtime for:
process_payment_with_signature- merchant payment history queries
cleanup_expired_payments
Benchmark results help identify optimization targets and compare the cost of hot-path operations.
Install cargo-llvm-cov once:
cargo install cargo-llvm-cov
rustup component add llvm-tools-previewGenerate a local HTML report:
COVERAGE=1 ./scripts/test.sh
# Report: coverage/index.html
# lcov data: lcov.infoCI enforces a minimum 80% line coverage threshold and uploads both the HTML report and lcov.info as build artifacts.
Test coverage includes:
- Merchant registration and deactivation
- Payment processing with signature verification
- Duplicate order ID rejection
- Refund initiation, approval, rejection, and execution
- Refund window and amount validation
- Multi-signature payment threshold enforcement
- Paginated history queries with filters and sorting
- Global statistics tracking
- Payment cleanup by age
A docker-compose.yml is provided to spin up a local Stellar node with Soroban RPC enabled.
# Validate the compose file before starting the local node
docker compose -f docker-compose.yml config
# 1. Start the local node and deploy the contract in one step
SOURCE_ACCOUNT=<secret-key> ./scripts/local_up.sh
# 2. Initialise admin (use the CONTRACT_ID printed by the script)
stellar contract invoke \
--id <CONTRACT_ID> \
--source-account <admin-secret-key> \
--rpc-url http://localhost:8000/soroban/rpc \
--network-passphrase "Standalone Network ; February 2017" \
-- set_admin \
--admin <admin-address>
# Stop the node when done
docker compose downSecrets and local credentials should never be committed to the repository. Use environment variables or local .env files, and keep .env.example as the only example configuration file in source control.
Works on Linux and macOS (requires Docker Desktop or Docker Engine with Compose v2).
The smoke test script validates that the deployed contract is functional by exercising the admin initialization, merchant registration, payment path, and merchant retrieval.
CONTRACT_ID=<contract-id> \
ADMIN_KEY=<admin-secret> \
MERCHANT_KEY=<merchant-secret> \
PAYER_KEY=<payer-secret> \
TOKEN_ADDRESS=<token-address> \
ADMIN_ADDRESS=<admin-address> \
MERCHANT_ADDRESS=<merchant-address> \
PAYER_ADDRESS=<payer-address> \
NETWORK=testnet \
./scripts/smoke_test.shBy default the script automatically generates a throwaway ed25519 keypair, derives the canonical signature payload (see docs/signature-format.md), signs it, and passes the real signature to process_payment_with_signature. No manual key management is required for a standard run.
CONTRACT_ID— deployed contract IDADMIN_KEY— admin account secret keyMERCHANT_KEY— merchant account secret keyPAYER_KEY— payer account secret keyTOKEN_ADDRESS— testnet SAC token address used for paymentADMIN_ADDRESS— admin public addressMERCHANT_ADDRESS— merchant public addressPAYER_ADDRESS— payer public addressNETWORK— target network (testnetby default)
The smoke test exercises real ed25519 signature verification by default. scripts/generate_smoke_keypair.sh handles key generation and signing:
- Queries
get_merchant_nonce(merchant_address)from the chain. - Constructs the canonical payload:
network_id (32 B) || contract_address XDR || nonce u64 BE (8 B) || order_id ScVal XDR || amount i128 BE (16 B) - Generates a fresh throwaway ed25519 keypair using Node.js built-ins.
- Signs the payload and exports
SMOKE_SIG,SMOKE_PUBKEY, andSMOKE_NONCE.
For the full payload specification see docs/signature-format.md.
You may supply your own pre-computed values by setting all three variables before calling the script:
export SMOKE_SIG=<128-hex-char signature>
export SMOKE_PUBKEY=<64-hex-char public key>
export SMOKE_NONCE=<nonce u64>
./scripts/smoke_test.shOr run the helper manually:
eval "$(./scripts/generate_smoke_keypair.sh \
--contract-id "$CONTRACT_ID" \
--merchant "$MERCHANT_ADDRESS" \
--order-id "SMOKE_$(date +%s)" \
--amount 1 \
--network testnet)"
./scripts/smoke_test.sh
⚠️ Zeroed values are only valid for local/test builds. The testnet WASM is compiled with--releaseand does not include the#[cfg(test)]bypass inverify_signature. Passing all-zero signatures against a live deployment will fail withInvalidSignature.
The smoke test passes when each step succeeds without returning a non-zero exit code. It executes:
set_adminregister_merchantprocess_payment_with_signature(with a genuine ed25519 signature)get_merchant
On success, the script prints:
✅ Smoke test passed.
To run the smoke test from GitHub Actions, set these repository secrets:
TESTNET_ADMIN_KEYTESTNET_MERCHANT_KEYTESTNET_PAYER_KEYTESTNET_TOKEN_ADDRESSTESTNET_ADMIN_ADDRESSTESTNET_MERCHANT_ADDRESSTESTNET_PAYER_ADDRESS
The CI workflows (testnet-smoke.yml and smoke_test.yml) automatically run generate_smoke_keypair.sh before the smoke test step — no additional secrets are needed for signature generation.
For a complete list of contract error codes, their descriptions, and remediation steps, see docs/errors.md.
# Set admin (one-time)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_admin --admin $ADMIN_ADDR
# Transfer admin rights
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- transfer_admin --current_admin $ADMIN_ADDR --new_admin $NEW_ADMIN_ADDR
# Add allowed token (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- add_allowed_token --admin $ADMIN_ADDR --token $TOKEN_ADDR
# Remove allowed token (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- remove_allowed_token --admin $ADMIN_ADDR --token $TOKEN_ADDR
# Set platform fee (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_platform_fee --admin $ADMIN_ADDR --fee_bps 250 --fee_recipient $FEE_RECIPIENT_ADDR
# Set large payment threshold (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_large_payment_threshold --admin $ADMIN_ADDR --threshold 100000
# Set payment cleanup period (seconds)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_payment_cleanup_period --admin $ADMIN_ADDR --period 7776000
# Set multisig expiry duration (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_multisig_expiry_duration --admin $ADMIN_ADDR --duration 2592000
# Set refund window (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_refund_window --admin $ADMIN_ADDR --window_secs 2592000
# Set minimum refund amount (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- set_min_refund_amount --admin $ADMIN_ADDR --amount 100
# Pause the contract (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- pause_contract --admin $ADMIN_ADDR
# Unpause the contract (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- unpause_contract --admin $ADMIN_ADDR
# Get contract version
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_contract_version# Check registration
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- is_registered --merchant_address $MERCHANT_ADDR
# Register
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- register_merchant \
--merchant_address $MERCHANT_ADDR \
--name "My Store" \
--description "Store description" \
--contact_info "contact@store.com" \
--category Retail
# Update merchant profile
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- update_merchant \
--merchant_address $MERCHANT_ADDR \
--name "My Store Updated" \
--description "Updated description" \
--contact_info "support@store.com" \
--category Retail
# Verify merchant (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- verify_merchant --admin $ADMIN_ADDR --merchant_address $MERCHANT_ADDR
# Unverify merchant (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- unverify_merchant --admin $ADMIN_ADDR --merchant_address $MERCHANT_ADDR
# Reactivate merchant (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- reactivate_merchant --admin $ADMIN_ADDR --merchant_address $MERCHANT_ADDR
# Deactivate merchant (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- deactivate_merchant --admin $ADMIN_ADDR --merchant_address $MERCHANT_ADDR
# Get merchant info
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_merchant --merchant_address $MERCHANT_ADDR
# List merchants (admin only, cursor-based pagination)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- get_merchants --admin $ADMIN_ADDR --cursor null --limit 10Merchants in the EU can exercise their right to erasure under GDPR Article 17. See PRIVACY.md for the full policy and docs/merchant-onboarding.md#data-deletion for step-by-step instructions.
# Step 1 — merchant submits deletion request (only the merchant can call this)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- request_merchant_data_deletion \
--merchant $MERCHANT_ADDR
# Step 2 — admin confirms and executes the anonymisation within 30 days
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- confirm_merchant_data_deletion \
--admin $ADMIN_ADDR \
--merchant $MERCHANT_ADDROn completion the name, description, and contact_info fields are replaced with [deleted] and a lumenflow/merchant_data_deleted event is emitted.
For detailed information on the signature payload format and how to build it in various languages, see docs/signature-format.md.
For batch payment processing (up to 10 items per call), error codes, partial failure handling, and idempotent re-submission, see docs/batch-payments.md.
# Process payment with signature
stellar contract invoke --id $CONTRACT_ID --source-account $PAYER_KEY --network $NETWORK \
-- process_payment_with_signature \
--payer $PAYER_ADDR \
--order_id "ORDER_001" \
--merchant_address $MERCHANT_ADDR \
--token_address $TOKEN_ADDR \
--amount 1000 \
--memo "Invoice #001" \
--tags null \
--signature "<64-byte-signature>" \
--merchant_public_key "<32-byte-public-key>"
# Batch payment (atomic, up to 10 items)
stellar contract invoke --id $CONTRACT_ID --source-account $PAYER_KEY --network $NETWORK \
-- batch_payment \
--payments '[{"order_id":"ORDER_002","merchant_address":"$MERCHANT_ADDR","token_address":"$TOKEN_ADDR","amount":500,"memo":"Batch item 1","tags":null,"signature":"<64-byte-signature>","merchant_public_key":"<32-byte-public-key>"}]'
# Get payment by ID
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_payment_by_id --caller $CALLER_ADDR --order_id "ORDER_001"
# Get payment summary (public)
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_payment_summary --order_id "ORDER_001"
# Update payment status after a refund (merchant or admin)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- update_payment_status \
--caller $MERCHANT_ADDR \
--order_id "ORDER_001" \
--refunded_amount 500
# Archive payment (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- archive_payment_record --admin $ADMIN_ADDR --order_id "ORDER_001"
# Cleanup expired payments (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- cleanup_expired_payments --admin $ADMIN_ADDR# Create a payment request
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- create_payment_request \
--merchant $MERCHANT_ADDR \
--request_id "REQ_001" \
--token_address $TOKEN_ADDR \
--amount 2500 \
--memo "Invoice request" \
--ttl 86400
# Pay a payment request
stellar contract invoke --id $CONTRACT_ID --source-account $PAYER_KEY --network $NETWORK \
-- pay_payment_request --payer $PAYER_ADDR --request_id "REQ_001"
# Cancel an unexpired payment request early (merchant only)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- cancel_payment_request --caller $MERCHANT_ADDR --request_id "REQ_001"
# Bulk-remove all expired payment requests (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- cancel_expired_payment_requests --admin $ADMIN_ADDR# Merchant history (paginated, sorted by date descending)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- get_merchant_payment_history \
--merchant <merchant-address> \
--cursor null \
--limit 10 \
--filter null \
--sort_field Date \
--sort_order Descending
# Payer history with amount filter
stellar contract invoke --id $CONTRACT_ID --source-account $PAYER_KEY --network $NETWORK \
-- get_payer_payment_history \
--payer <payer-address> \
--cursor null \
--limit 10 \
--filter '{"amount_min":100,"amount_max":5000,"status":"Any"}' \
--sort_field Amount \
--sort_order Ascending
# Global stats (admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $ADMIN_KEY --network $NETWORK \
-- get_global_payment_stats \
--admin $ADMIN_ADDR \
--date_start null \
--date_end null
# Merchant stats (merchant only)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- get_merchant_stats --merchant $MERCHANT_ADDRFilter fields: date_start, date_end, amount_min, amount_max, token, status (Any | Completed | PartiallyRefunded | FullyRefunded)
Sort fields: Date | Amount
Sort orders: Ascending | Descending
Pagination: cursor-based using order_id; max 100 results per page.
PaymentPage response fields:
payments: records returned for the current pagenext_cursor: cursor to request the next page (ornullif none)total_matching: total count of records that match the query before applyinglimit
Refund rules:
- Window: 30 days from
paid_at - Minimum refund amount: 100 stroops by default (admin-configurable via
set_min_refund_amount) - Partial refunds allowed; cumulative total cannot exceed original amount
- Initiator: payer or merchant
- Approver/Rejector: merchant or admin
- Executor: merchant (signs the token transfer)
# Initiate
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- initiate_refund \
--caller <caller-address> \
--refund_id "REFUND_001" \
--order_id "ORDER_001" \
--amount 500 \
--reason "Customer request"
# Approve
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- approve_refund --caller <merchant-address> --refund_id "REFUND_001"
# Reject
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- reject_refund --caller <merchant-address> --refund_id "REFUND_001"
# Execute (merchant signs the transfer)
stellar contract invoke --id $CONTRACT_ID --source-account $MERCHANT_KEY --network $NETWORK \
-- execute_refund --refund_id "REFUND_001"
# Get refund status
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_refund --refund_id "REFUND_001"
# List all refunds for an order (payer, merchant, or admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $CALLER_KEY --network $NETWORK \
-- get_refunds_for_order --caller <caller-address> --order_id "ORDER_001"# Initiate
stellar contract invoke --id $CONTRACT_ID --source-account $INITIATOR_KEY --network $NETWORK \
-- initiate_multisig_payment \
--initiator <initiator-address> \
--payment_id "MS_001" \
--merchant_address <merchant-address> \
--token_address <token-address> \
--amount 5000 \
--signers '["<signer1>","<signer2>"]' \
--required_signatures 2
# Sign
stellar contract invoke --id $CONTRACT_ID --source-account $SIGNER_KEY --network $NETWORK \
-- sign_multisig_payment \
--signer <signer-address> \
--payment_id "MS_001" \
--signature <signature-bytes>
# Execute (once threshold met)
stellar contract invoke --id $CONTRACT_ID --source-account $PAYER_KEY --network $NETWORK \
-- execute_multisig_payment --payer <payer-address> --payment_id "MS_001"
# Cancel multisig payment (initiator or admin only)
stellar contract invoke --id $CONTRACT_ID --source-account $INITIATOR_KEY --network $NETWORK \
-- cancel_multisig_payment \
--caller $INITIATOR_ADDR \
--payment_id "MS_001"
# Get multisig payment details
stellar contract invoke --id $CONTRACT_ID --source-account $SIGNER_KEY --network $NETWORK \
-- get_multisig_payment \
--caller $SIGNER_ADDR \
--payment_id "MS_001"Full event payload documentation and subscription guides can be found in docs/events-reference.md.
For production monitoring — Horizon SSE streaming, alert thresholds, and example code — see docs/monitoring.md.
| Event name | Trigger |
|---|---|
lumenflow/admin_set |
Admin initialised |
lumenflow/merchant_registered |
New merchant registered |
lumenflow/merchant_updated |
Merchant profile updated |
lumenflow/merchant_deactivated |
Merchant deactivated |
lumenflow/payment_processed |
Payment completed |
lumenflow/payment_archived |
Payment record removed |
lumenflow/refund_initiated |
Refund request opened |
lumenflow/refund_approved |
Refund approved |
lumenflow/refund_rejected |
Refund rejected |
lumenflow/refund_executed |
Refund transfer completed |
lumenflow/multisig_initiated |
Multisig payment created |
lumenflow/multisig_executed |
Multisig payment executed |
lumenflow/payment_request_paid |
Payment request completed |
lumenflow/suspicious_activity |
Safety threshold exceeded |
lumenflow/merchant_deletion_requested |
Merchant submitted a GDPR data-deletion request |
lumenflow/merchant_data_deleted |
Merchant PII fields anonymised after admin confirmation |
The frontend/ directory contains three standalone HTML pages that let you interact with LumenFlow without any build step.
| Page | File | Purpose |
|---|---|---|
| Payment History | frontend/history.html |
Browse and filter your payment records |
| Payment Receipt | frontend/receipt.html |
View a receipt for a specific order |
| Multisig Payment | frontend/multisig.html |
Initiate and sign multi-signature payments |
All frontend pages ship with a manifest.json and a service worker (sw.js) so the payment UI can be installed on mobile devices and used offline for receipt viewing.
Install on Android (Chrome):
- Open
history.htmlorreceipt.htmlin Chrome on your Android device. - Tap the browser menu (⋮) and select "Add to Home screen" (or wait for the automatic install banner).
- Confirm the installation — LumenFlow will appear as a home-screen app.
Install on iOS (Safari):
- Open any page in Safari.
- Tap the Share button (□↑) and choose "Add to Home Screen".
- Tap Add — the app icon will appear on your home screen.
Install on desktop (Chrome / Edge):
- Open any page in the browser.
- Click the install icon (⊕) in the address bar, or open the browser menu and choose "Install LumenFlow".
Offline use: The service worker caches the app shell and mock receipt data on first load. Receipt pages work offline using cached data. When connectivity is restored the cache is updated automatically.
Lighthouse PWA score: Run a Lighthouse audit from Chrome DevTools (Lighthouse → Mobile → PWA) against a locally served build to verify the score. The target is 90+.
Simply open any file directly in a browser:
# Linux / macOS
xdg-open frontend/history.html # Linux
open frontend/history.html # macOS
# Or serve with any static server to avoid browser CORS restrictions
npx serve frontend
# then visit http://localhost:3000By default the pages run in demo mode — they render with hard-coded mock data so you can preview the UI without a deployed contract.
To switch to live mode, set the following environment variables before serving the pages (or edit the <script> block at the top of each HTML file):
| Variable | Description | Example |
|---|---|---|
LUMENFLOW_CONTRACT_ID |
Deployed contract address | CABC…XYZ |
LUMENFLOW_NETWORK |
Stellar network to connect to | testnet or mainnet |
LUMENFLOW_RPC_URL |
Soroban RPC endpoint | https://soroban-testnet.stellar.org |
Example using a simple HTTP server with injected config:
export LUMENFLOW_CONTRACT_ID="CABC...XYZ"
export LUMENFLOW_NETWORK="testnet"
export LUMENFLOW_RPC_URL="https://soroban-testnet.stellar.org"
npx serve frontendNote: The pages connect to Stellar Freighter or a compatible browser wallet for transaction signing. Install the Freighter extension before using live mode.
NETWORK=testnet SOURCE_ACCOUNT=<testnet-secret-key> ./scripts/deploy.shGet testnet XLM from the Stellar Friendbot.
LumenFlow supports independent, reproducible verification of the deployed contract binary. Every release publishes a SHA-256 hash in docs/release-hashes.md so that anyone can confirm the on-chain binary matches the open-source code.
# 1. Clone the repo at the release tag
git clone https://github.com/Gloriachinedu/lumenflow-contracts.git
cd lumenflow-contracts
git checkout v1.0.0 # replace with the target version
# 2. Install the pinned toolchain (reads rust-toolchain.toml automatically)
rustup show
# 3. Run the verification script
./scripts/verify-build.sh v1.0.0A passing run prints ✅ Hash match — build is reproducible for v1.0.0.
| Factor | Pinned by |
|---|---|
| Rust compiler version | rust-toolchain.toml (channel = "1.87.0") |
| All dependency versions | Cargo.lock (committed to this repo) |
| Compiler flags | [profile.release] in Cargo.toml |
# Download the released artifact from GitHub Releases
curl -LO https://github.com/Gloriachinedu/lumenflow-contracts/releases/download/v1.0.0/lumenflow_v1.0.0.wasm.sha256
cat lumenflow_v1.0.0.wasm.sha256Both the local build and the GitHub Release artifact must produce the same SHA-256.
For a full list of common errors (build, deploy, runtime, and upgrade) with causes and resolution steps, see the Troubleshooting Guide.
Quick reference for the most frequent issues:
WASM target missing:
rustup target add wasm32-unknown-unknownLocal network fails to start:
stellar network container restart localInsufficient XLM for fees: Fund your account via Friendbot (testnet) or acquire XLM (mainnet).
Test failures: Ensure soroban-sdk version in Cargo.toml matches rust-toolchain.toml channel.
Found an error not listed? Open a PR using the troubleshooting entry template.
A lightweight local preview server is included under frontend/ for working on static UI pages without a production build step.
Requirements: Node.js ≥ 18
# One-command start (installs deps on first run)
./scripts/dev.shOr run directly:
cd frontend
npm install # first time only
npm run dev # starts http://localhost:3000 with live reloadThe server watches **/*.html, **/*.css, and **/*.js inside frontend/ and refreshes the browser automatically on changes.
Need help or want to discuss LumenFlow?
- Discord Server: Join our Discord community to chat with developers and other users.
- Q&A Discussions: Ask questions in GitHub Discussions — Q&A.
- Developer Help: SDK, deployment, and tooling questions in Developer Help.
- Feature Requests: Propose and discuss new features in Feature Requests.
- Support Guidelines: See SUPPORT.md for where to get help and how to report bugs.
Merchants can receive real-time payment event notifications in their backend systems via the Horizon event stream. See docs/webhook-integration.md for a full guide including a Node.js example server and idempotency best practices.
See CONTRIBUTING.md. All contributions are welcome — bug fixes, features, documentation, and tests.
New contributors should start with the Developer Onboarding Guide.
See GOVERNANCE.md for project decision-making, the RFC process, and maintainer responsibilities.
We maintain localized versions of the README to support Spanish and Portuguese readers. The translated files are:
- Update the canonical
README.mdwith new content or structural changes. - Notify translators and update the corresponding localized files.
- Verify that key docs and examples are preserved in translations.
- Keep translations synchronized by reviewing changes during each release or docs update.
README.md— primary project overview and getting started guide.SECURITY.md— responsible disclosure and incident reporting.docs/events-reference.md— event payload definitions and integrations.sdk/README.md— SDK usage and helper method guidance.
See SECURITY.md for responsible disclosure instructions.
| Topic | Document |
|---|---|
| Reporting policy | SECURITY.md · .well-known/security.txt |
| Disclosure & incident-response workflow | docs/security/vulnerability-disclosure-and-incident-response.md |
| Incident response runbook | docs/runbooks/incident-response-runbook.md |
| Security regression catalogue | docs/security/regression-catalog.md (scripts/security-regression-check.sh) |
A formal third-party security audit of the LumenFlow smart contract is in progress before mainnet launch.
| Item | Detail |
|---|---|
| Engagement plan | docs/audit/audit-engagement-plan.md |
| Audit report | docs/audit/audit-report-v1.0.md |
| Audit scope | All public contract functions, storage layout, signature verification, access control |
| Status | 🔴 Pending — audit in progress |
| Mainnet deployment | Blocked until all Critical and High findings are resolved (scripts/audit-readiness-check.sh --mainnet) |
All Critical findings will have remediation PRs before mainnet deployment. A re-audit is scheduled after any Critical finding remediation.
MIT © 2026 LumenFlow Contributors