A complete backend API for the Jerota platform - a creator campaign and fan rewards system built with Express.js and MongoDB.
Jerota enables creators (musicians, YouTubers, etc.) to launch campaigns to fund content, while fans earn token rewards (USDC, USDT, LSK, etc.) for actions like streaming, sharing, commenting, liking, or following. Campaign budgets are locked on-chain (Lisk L2), but the backend handles offchain data management, action verification, and smart contract integration.
- User Management: Creator and fan registration with wallet-based authentication
- Campaign Management: Create, update, and manage creator campaigns with reward rules
- Action Verification: Verify fan actions on external platforms (Spotify, YouTube, Twitter)
- Reward System: Token-based rewards with blockchain integration
- Smart Contract Integration: Validate tokens against Lisk L2 smart contracts
- RESTful API: Complete API with validation, error handling, and pagination
- Framework: Express.js
- Database: MongoDB with Mongoose
- Blockchain: Ethers.js for Lisk L2 integration
- Validation: Express-validator
- Logging: Winston
- Environment: Node.js (LTS)
/jerota-backend
├── /config
│ └── db.js # MongoDB connection setup
├── /models
│ ├── User.js # User schema
│ ├── Campaign.js # Campaign schema
│ └── index.js # Model exports
├── /routes
│ ├── users.js # User endpoints
│ ├── campaigns.js # Campaign endpoints
│ └── rewards.js # Reward endpoints
├── /controllers
│ ├── userController.js
│ ├── campaignController.js
│ └── rewardController.js
├── /middleware
│ ├── auth.js # Authentication middleware
│ └── validate.js # Input validation
├── /services
│ ├── blockchain.js # Smart contract interaction
│ └── verification.js # External API verification
├── /utils
│ └── errorHandler.js # Centralized error handling
├── app.js # Express app setup
├── server.js # Server entry point
├── package.json
├── .env # Environment variables
└── README.md
- Clone the repository
git clone <repository-url>
cd jerota-backend- Install dependencies
npm install- Set up environment variables
Copy
.envfile and configure:
PORT=3000
MONGODB_URI=mongodb://localhost:27017/jerota
LISK_L2_RPC_URL=https://rpc.api.lisk.com
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
YOUTUBE_API_KEY=your_youtube_api_key
TWITTER_BEARER_TOKEN=your_twitter_bearer_token
NODE_ENV=development-
Start MongoDB Make sure MongoDB is running locally or update
MONGODB_URIfor remote connection. -
Run the application
# Development
npm run dev
# Production
npm starthttp://localhost:3000/api
Include wallet address in request headers:
x-wallet-address: 0x1234567890123456789012345678901234567890
POST /api/users/register
Content-Type: application/json
{
"walletAddress": "0x1234567890123456789012345678901234567890",
"username": "creator123",
"role": "creator",
"email": "creator@example.com",
"twitter": "@creator123",
"instagram": "creator123"
}GET /api/users/0x1234567890123456789012345678901234567890PUT /api/users/0x1234567890123456789012345678901234567890
x-wallet-address: 0x1234567890123456789012345678901234567890
Content-Type: application/json
{
"username": "newusername",
"email": "newemail@example.com"
}POST /api/campaigns
x-wallet-address: 0x1234567890123456789012345678901234567890
Content-Type: application/json
{
"title": "My Music Campaign",
"description": "Support my new album",
"budget": {
"amount": 1000,
"token": {
"address": "0xa0b86991c431e803e5f6d5024d9650441c8c5c044",
"name": "USDC"
}
},
"rewardRules": [
{
"action": "stream",
"rewardAmount": 0.5,
"token": {
"address": "0xa0b86991c431e803e5f6d5024d9650441c8c5c044",
"name": "USDC"
},
"maxClaims": 10
}
],
"startDate": "2024-01-01T00:00:00Z",
"endDate": "2024-12-31T23:59:59Z",
"contentUrl": "https://open.spotify.com/track/example"
}GET /api/campaigns/60f7b3b3b3b3b3b3b3b3b3b3GET /api/campaigns?status=active&page=1&limit=10PUT /api/campaigns/60f7b3b3b3b3b3b3b3b3b3b3
x-wallet-address: 0x1234567890123456789012345678901234567890
Content-Type: application/json
{
"status": "paused",
"description": "Updated description"
}POST /api/campaigns/60f7b3b3b3b3b3b3b3b3b3b3/participate
x-wallet-address: 0xfan1234567890123456789012345678901234567890
Content-Type: application/json
{
"action": "stream",
"proof": "spotify_stream_proof_data"
}POST /api/rewards/claim
x-wallet-address: 0xfan1234567890123456789012345678901234567890
Content-Type: application/json
{
"campaignId": "60f7b3b3b3b3b3b3b3b3b3b3",
"action": "stream",
"proof": "verified_action_proof"
}GET /api/rewards/0xfan1234567890123456789012345678901234567890?page=1&limit=10GET /api/rewards/campaign/60f7b3b3b3b3b3b3b3b3b3b3/stats- Creator Registration
curl -X POST http://localhost:3000/api/users/register \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x1234567890123456789012345678901234567890",
"username": "musiccreator",
"role": "creator",
"email": "creator@example.com"
}'- Fan Registration
curl -X POST http://localhost:3000/api/users/register \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0xfan1234567890123456789012345678901234567890",
"username": "musicfan",
"role": "fan",
"email": "fan@example.com"
}'- Create Campaign
curl -X POST http://localhost:3000/api/campaigns \
-H "Content-Type: application/json" \
-H "x-wallet-address: 0x1234567890123456789012345678901234567890" \
-d '{
"title": "Stream My New Song",
"description": "Get rewarded for streaming my latest track",
"budget": {
"amount": 500,
"token": {
"address": "0xa0b86991c431e803e5f6d5024d9650441c8c5c044",
"name": "USDC"
}
},
"rewardRules": [{
"action": "stream",
"rewardAmount": 0.1,
"token": {
"address": "0xa0b86991c431e803e5f6d5024d9650441c8c5c044",
"name": "USDC"
}
}],
"startDate": "2024-01-01T00:00:00Z",
"endDate": "2024-12-31T23:59:59Z",
"contentUrl": "https://open.spotify.com/track/example"
}'- Fan Participation
curl -X POST http://localhost:3000/api/campaigns/CAMPAIGN_ID/participate \
-H "Content-Type: application/json" \
-H "x-wallet-address: 0xfan1234567890123456789012345678901234567890" \
-d '{
"action": "stream",
"proof": "spotify_listening_history_proof"
}'- Claim Reward
curl -X POST http://localhost:3000/api/rewards/claim \
-H "Content-Type: application/json" \
-H "x-wallet-address: 0xfan1234567890123456789012345678901234567890" \
-d '{
"campaignId": "CAMPAIGN_ID",
"action": "stream",
"proof": "verified_stream_proof"
}'The API returns consistent error responses:
{
"success": false,
"error": "Error message description"
}Common HTTP status codes:
200: Success201: Created400: Bad Request (validation errors)401: Unauthorized (missing/invalid wallet address)403: Forbidden (insufficient permissions)404: Not Found500: Internal Server Error
All endpoints include comprehensive input validation:
- Wallet addresses must match Ethereum format (
0x+ 40 hex characters) - Usernames must be 3-30 characters, alphanumeric
- Token addresses are validated against smart contract allowed tokens
- Campaign dates must be valid and end date after start date
- Reward amounts must be positive numbers
- Wallet-based Authentication: Users authenticate with wallet addresses
- Role-based Authorization: Creators and fans have different permissions
- Input Sanitization: All inputs are validated and sanitized
- Error Handling: Centralized error handling prevents information leakage
- CORS Configuration: Configurable cross-origin resource sharing
The backend integrates with Lisk L2 blockchain:
- Token Validation: Validates campaign tokens against smart contract
- TVL Calculation: Retrieves Total Value Locked from on-chain data
- Allowed Tokens: Queries smart contract for permitted tokens
Currently supported tokens (mock data):
- USDC:
0xa0b86991c431e803e5f6d5024d9650441c8c5c044 - USDT:
0xdac17f958d2ee523a2206206994597c13d831ec7 - LSK:
0x6033f7f88332b8db6ad452b7c6d5bb643990ae3f - UNI:
0x1f9840a85d5af5bf1d1762f925bdaddc4201f984
The platform supports verification for multiple actions across platforms:
- Spotify: Stream, Follow
- YouTube: Stream, Like, Comment
- Twitter: Share, Follow
- Instagram: Follow
- User performs action on external platform
- User submits proof (API response, screenshot hash, etc.)
- Backend verifies action through platform APIs
- Verified actions become eligible for rewards
The project includes comprehensive integration and unit tests using Jest and Supertest.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage report
npm run test:coverage- Integration Tests: Test complete API endpoints with database
- Unit Tests: Test individual services and utilities
- Test Database: Uses MongoDB Memory Server for isolated testing
tests/integration/- API endpoint teststests/unit/- Service and utility teststests/setup.js- Test configuration and database setup
Interactive API documentation is available via Swagger UI:
# Start the server
npm run dev
# Visit the documentation
http://localhost:3002/api-docsThe Swagger documentation includes:
- Complete API endpoint documentation
- Request/response schemas
- Authentication requirements
- Example requests and responses
The project follows standard Node.js/Express conventions:
- Use async/await for asynchronous operations
- Implement proper error handling
- Include JSDoc comments for functions
- Follow RESTful API design principles
- New Routes: Add to appropriate route file in
/routes - Controllers: Implement business logic in
/controllers - Validation: Add validation rules in
/middleware/validate.js - Services: External integrations go in
/services
- Set production environment variables
- Configure MongoDB connection string
- Set up Lisk L2 RPC endpoint
- Configure external API credentials
- Use process manager (PM2, Docker)
- Set up proper logging and monitoring
- Configure reverse proxy (Nginx)
- Enable HTTPS
- Set up database backups
- Configure rate limiting
- Fork the repository
- Create a feature branch
- Implement changes with tests
- Submit a pull request
MIT License - see LICENSE file for details.
For questions or issues:
- Create an issue in the repository
- Check the API documentation
- Review the example workflows above