A modular, production-grade on-chain loyalty platform built on the Stellar network using Soroban smart contracts. Businesses create reward campaigns, users earn tokenized incentives (LYT), and everything is stored transparently on-chain.
See our Glossary for definitions of domain-specific terms and our Changelog for recent updates.
┌─────────────────────────────────────────────────────────────────┐
│ Stellar Network │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ Token (LYT) │◄──│ Rewards Contract│──►│Campaign Contract│ │
│ │ mint/burn │ │ claim/redeem │ │ create/manage │ │
│ └──────────────┘ └──────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▲ ▲
│ Soroban RPC │ Events
│ │
┌─────────┴───────────────────┴──────────────────────────────────┐
│ Backend (Node.js / Express) │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ Indexer │ │ Campaign Service │ │ Reward Service │ │
│ │ (event poll) │ │ (DB read/write) │ │ (DB read/write)│ │
│ └──────┬───────┘ └────────┬─────────┘ └───────┬────────┘ │
│ └───────────────────┼─────────────────────┘ │
│ ▼ │
│ PostgreSQL DB │
└─────────────────────────────────────────────────────────────────┘
▲
│ REST API
│
┌─────────┴──────────────────────────────────────────────────────┐
│ Frontend (Next.js 14) │
│ │
│ /dashboard — claim rewards, view balance │
│ /merchant — create & manage campaigns │
│ /analytics — campaign performance stats │
│ │
│ Freighter wallet integration (sign & submit transactions) │
└────────────────────────────────────────────────────────────────┘
| Contract | Description |
|---|---|
token |
Fungible LYT token — mint, burn, transfer. Admin-controlled mint. |
campaign |
Merchants create campaigns with reward amount + expiration. |
rewards |
Users claim rewards (mints LYT). Redeem burns LYT. Double-claim prevented. |
- Rust +
wasm32-unknown-unknowntarget - Stellar CLI
- Docker + Docker Compose
- Node.js 20+
git clone https://github.com/your-org/soroban-loyalty
cd soroban-loyalty
cp .env.example .envdocker-compose up --buildServices:
- Soroban local node:
http://localhost:8000 - Backend API:
http://localhost:3001 - Frontend:
http://localhost:3000 - PostgreSQL:
localhost:5432
Start PostgreSQL (or use Docker just for DB):
docker-compose up postgres -dBackend:
cd backend
npm install
npm run devFrontend:
cd frontend
npm install
npm run devrustup target add wasm32-unknown-unknown./scripts/deploy-contracts.sh local <YOUR_SECRET_KEY>./scripts/deploy-contracts.sh testnet <YOUR_SECRET_KEY>The script builds all three contracts, deploys them, initializes them with correct cross-contract references, and updates your .env automatically.
# All contracts
cargo test
# Individual contract
cargo test -p soroban-loyalty-token
cargo test -p soroban-loyalty-campaign
cargo test -p soroban-loyalty-rewardsTest coverage:
- Token: mint, transfer, burn, overflow/underflow guards
- Campaign: creation, expiry validation, deactivation, time-based expiry
- Rewards: claim, double-claim prevention, inactive campaign rejection, expired campaign rejection, redeem burns tokens
| Method | Path | Description |
|---|---|---|
GET |
/campaigns |
List all campaigns |
GET |
/campaigns/:id |
Get campaign by ID |
| Method | Path | Description |
|---|---|---|
GET |
/user/:address/rewards |
Get all rewards for a user |
| Method | Path | Description |
|---|---|---|
GET |
/health |
Service health check |
Claim and redeem operations are submitted directly to the Soroban RPC from the frontend (signed by Freighter). The backend indexes the resulting on-chain events.
soroban-loyalty/
├── contracts/
│ ├── token/src/lib.rs # LYT fungible token
│ ├── campaign/src/lib.rs # Campaign management
│ └── rewards/src/lib.rs # Claim & redeem logic
├── backend/
│ └── src/
│ ├── index.ts # Express server entry
│ ├── db.ts # PostgreSQL pool
│ ├── soroban.ts # RPC client
│ ├── indexer/indexer.ts # Event indexer
│ ├── services/ # campaign + reward services
│ └── routes/ # REST route handlers
├── frontend/
│ └── src/
│ ├── app/ # Next.js App Router pages
│ ├── components/ # WalletConnector, CampaignCard, RewardList
│ ├── context/ # WalletContext (Freighter state)
│ └── lib/ # api.ts, soroban.ts, freighter.ts
├── database/schema.sql # PostgreSQL schema
├── scripts/deploy-contracts.sh # One-shot deploy script
├── docker-compose.yml
└── .env.example
- All sensitive contract functions use
require_auth() - Double-claim prevention: claimed state is written before external calls (reentrancy guard)
- Overflow-safe arithmetic via
checked_add/ Rust'soverflow-checks = truein release - Token minting is restricted to the Rewards contract (set as admin during deploy)
- No secret keys in code — all keys via environment variables
This project follows the Code of Conduct.
By participating, you are expected to uphold these guidelines.