Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions contracts/subscription/src/achievements.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/// Gamification & Achievement tracking module for SubTrackr subscriptions.
///
/// Records user achievement unlocks on-chain and awards loyalty/gamification XP.
use soroban_sdk::{contracttype, Address, Env, Symbol, Vec};

use crate::{storage_persistent_get, storage_persistent_set};

/// Storage key for achievement tracking.
#[contracttype]
#[derive(Clone, Debug, PartialEq)]
pub enum AchievementKey {
/// List of earned achievement IDs (Symbols) for a subscriber.
UserAchievements(Address),
}

/// Retrieve all unlocked achievement IDs (Symbols) for a subscriber.
pub fn get_earned_achievements(
env: &Env,
storage: &Address,
subscriber: &Address,
) -> Vec<Symbol> {
storage_persistent_get::<Vec<Symbol>>(
env,
storage,
AchievementKey::UserAchievements(subscriber.clone()),
)
.unwrap_or_else(|| Vec::new(env))
}

/// Check if a subscriber has unlocked a specific achievement.
pub fn has_achievement(
env: &Env,
storage: &Address,
subscriber: &Address,
achievement_id: Symbol,
) -> bool {
let achievements = get_earned_achievements(env, storage, subscriber);
achievements.contains(achievement_id)
}

/// Record an achievement unlock for a subscriber.
/// If the achievement was not already unlocked, records it and returns true.
pub fn record_achievement(
env: &Env,
storage: &Address,
subscriber: &Address,
achievement_id: Symbol,
) -> bool {
let mut achievements = get_earned_achievements(env, storage, subscriber);
if achievements.contains(achievement_id) {
return false;
}
achievements.push_back(achievement_id);
storage_persistent_set(
env,
storage,
AchievementKey::UserAchievements(subscriber.clone()),
&achievements,
);
true
}
1 change: 1 addition & 0 deletions contracts/subscription/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod gas_profiler;
mod gas_storage;
mod invoice_branding;
mod revenue;
pub mod achievements;
#[cfg(test)]
mod test;

Expand Down
109 changes: 109 additions & 0 deletions docs/gamification-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SubTrackr Gamification System Guide

## Overview
The SubTrackr Gamification System is engineered to boost subscriber engagement and retention through interactive rewards, milestone achievements, dynamic leaderboards, and on-chain blockchain verification.

---

## 1. System Architecture

The gamification architecture consists of three integrated layers:

```mermaid
graph TD
A[UI Layer: GamificationScreen & Components] --> B[State Layer: Zustand Store / AsyncStorage]
B --> C[Service Layer: GamificationService]
C --> D[On-Chain Layer: Soroban Smart Contract achievements.rs]
B --> E[Notification Layer: Local Alerts]
```

### Key Modules:
- **`src/types/gamification.ts`**: Core TypeScript interfaces for `Achievement`, `RewardDefinition`, `RewardItem`, `GamificationConfig`, `GamificationAnalytics`, and `LeaderboardEntry`.
- **`src/services/gamificationService.ts`**: Static definitions of achievements, badges, rewards catalog, multi-category leaderboard generators, and social sharing helpers.
- **`src/store/gamificationStore.ts`**: Zustand persistent store managing user points, levels, unlocked items, reward claims, and analytics calculations.
- **`contracts/subscription/src/achievements.rs`**: On-chain Stellar/Soroban smart contract module for decentralized recording and validation of unlocked milestones.

---

## 2. Achievement Triggers & Definitions

Achievements are evaluated whenever significant user actions occur, tracked via the `AchievementTrigger` enum:
- `SUBSCRIPTION_ADDED`: Adding new recurring subscriptions to the tracker.
- `CRYPTO_PAYMENT`: Settling subscription invoices using cryptocurrency.
- `SEGMENT_CREATED`: Categorizing subscriptions into custom analytical segments.
- `POINTS_MILESTONE`: Accumulating lifetime loyalty points.
- `STREAK_MILESTONE`: Maintaining consecutive on-time payment cycles without failures.
- `REFERRAL_MADE`: Inviting new merchants or users to SubTrackr.

### Sample Achievements & Rewards
| Achievement ID | Name | Criteria | XP Awarded | Reward Type | Reward Value |
|---|---|---|---|---|---|
| `first_sub` | Getting Started | Add 1 subscription | 50 XP | Loyalty Credit | 100 Credits |
| `tracker_pro` | Tracker Pro | Add 5 subscriptions | 200 XP | Discount Coupon | 10% Off (`PRO-10OFF`) |
| `crypto_pioneer` | Crypto Pioneer | Pay with crypto | 150 XP | Loyalty Credit | 500 Credits |
| `point_hoarder` | Point Hoarder | Earn 5,000 pts | 300 XP | Loyalty Credit | 1,000 Bonus Credits |
| `loyal_member` | Loyal Member | Earn 15,000 pts | 500 XP | VIP Discount | 20% Lifetime (`VIP-20OFF`) |
| `streak_master` | Streak Master | 30-charge streak | 200 XP | Discount Coupon | 15% Off (`STREAK-15OFF`) |
| `referral_pro` | Networker | Refer 5 friends | 250 XP | Ambassador Credit| 2,500 Credits |

---

## 3. Reward Distribution System

When `checkAchievements(trigger, metadata)` successfully unlocks an achievement:
1. **XP & Leveling**: Points are added to the user's total. If total points exceed `100 * (level ^ 1.5)`, a Level Up event fires.
2. **Badge Unlocking**: Any linked `badgeId` is unlocked and stored in `earnedBadges`.
3. **Reward Generation**: If the achievement defines a `reward`, a unique `RewardItem` is generated with coupon code prefixes or credit vouchers and placed in `earnedRewards`.
4. **Redemption Flow**: Users can view rewards in the **Rewards Catalog** tab, copy coupon codes directly to their device clipboard, claim loyalty credits, and mark coupons as redeemed after application.

---

## 4. Leaderboard & Social Sharing

### Multi-Category Leaderboards
The leaderboard system supports three interactive views:
- **All Time**: Ranked by cumulative XP earned across all actions.
- **Weekly**: Ranked by recent weekly XP acceleration.
- **Streaks**: Ranked by consecutive on-time charge days (`streak`).

### Social Sharing Integration
Using the React Native `Share` API, users can broadcast their progress:
- **Badge Share**: Share specific unlocked badges with custom emoji banners and hashtags (`#SubTrackr #Badges`).
- **Level Share**: Broadcast overall tracker level and XP to invite friends and build network density.

---

## 5. Gamification Analytics

The `getAnalytics()` method computes real-time engagement telemetry:
- **Completion Rate**: Percentage of available achievements unlocked (`0 - 100%`).
- **Category Breakdown**: Mapping of unlocked milestones across trigger types.
- **Points History**: Timestamped audit trail of up to 100 recent XP earnings and unlock reasons.

---

## 6. Store Configuration

Users have granular control over their gamification experience via `GamificationConfig`:
- `soundEffectsEnabled`: Toggle audio feedback on unlocks.
- `notificationsEnabled`: Enable/disable local alerts (`presentLocalNotification`).
- `showOnLeaderboard`: Toggle public display of username and rank on leaderboards.
- `dailyReminderEnabled`: Opt-in to daily push notifications to maintain payment streaks.

---

## 7. On-Chain Contract Integration (`achievements.rs`)

For enterprise and crypto-native users, achievement symbols are persisted to Stellar Soroban contract storage via `StorageKey::UserAchievements(Address)`.

### Rust Contract API:
```rust
/// Record an achievement unlock on-chain
pub fn record_achievement(env: &Env, storage: &Address, subscriber: &Address, achievement_id: Symbol) -> bool;

/// Query all earned achievement Symbols for a subscriber
pub fn get_earned_achievements(env: &Env, storage: &Address, subscriber: &Address) -> Vec<Symbol>;

/// Check whether an achievement is unlocked on-chain
pub fn has_achievement(env: &Env, storage: &Address, subscriber: &Address, achievement_id: Symbol) -> bool;
```
Loading