|
2 | 2 | mod gas_profiler; |
3 | 3 | mod gas_storage; |
4 | 4 | mod gas_optimization; |
| 5 | +mod loyalty; |
5 | 6 | use soroban_sdk::{token, Address, Env, IntoVal, String, TryFromVal, Val, Vec}; |
6 | 7 | use subtrackr_types::{ |
7 | 8 | Interval, Invoice, Plan, StorageKey, Subscription, SubscriptionStatus, TimeRange, |
@@ -686,6 +687,15 @@ impl SubTrackrSubscription { |
686 | 687 | (sub.subscriber.clone(), plan.price, 100_000u64, now), |
687 | 688 | ); |
688 | 689 |
|
| 690 | + // Accumulate loyalty points after successful charge. |
| 691 | + loyalty::accumulate_points( |
| 692 | + &env, |
| 693 | + &storage, |
| 694 | + &sub.subscriber, |
| 695 | + plan.price, |
| 696 | + now, |
| 697 | + ); |
| 698 | + |
689 | 699 | if let Some(invoice_addr) = invoice_contract(&env, &storage) { |
690 | 700 | let period = TimeRange { |
691 | 701 | start: sub.last_charged_at, |
@@ -1045,6 +1055,140 @@ impl SubTrackrSubscription { |
1045 | 1055 | revenue::get_revenue_schedule(&env, &storage, subscription_id) |
1046 | 1056 | } |
1047 | 1057 |
|
| 1058 | + // ── Loyalty & Rewards API ── |
| 1059 | + |
| 1060 | + pub fn initialize_loyalty( |
| 1061 | + env: Env, |
| 1062 | + proxy: Address, |
| 1063 | + storage: Address, |
| 1064 | + config: subtrackr_types::LoyaltyConfig, |
| 1065 | + ) { |
| 1066 | + proxy.require_auth(); |
| 1067 | + get_admin(&env, &storage).require_auth(); |
| 1068 | + loyalty::set_loyalty_config(&env, &storage, &config); |
| 1069 | + } |
| 1070 | + |
| 1071 | + pub fn update_loyalty_config( |
| 1072 | + env: Env, |
| 1073 | + proxy: Address, |
| 1074 | + storage: Address, |
| 1075 | + config: subtrackr_types::LoyaltyConfig, |
| 1076 | + ) { |
| 1077 | + proxy.require_auth(); |
| 1078 | + get_admin(&env, &storage).require_auth(); |
| 1079 | + loyalty::set_loyalty_config(&env, &storage, &config); |
| 1080 | + } |
| 1081 | + |
| 1082 | + pub fn get_loyalty_config( |
| 1083 | + env: Env, |
| 1084 | + proxy: Address, |
| 1085 | + storage: Address, |
| 1086 | + ) -> Option<subtrackr_types::LoyaltyConfig> { |
| 1087 | + proxy.require_auth(); |
| 1088 | + loyalty::get_loyalty_config(&env, &storage) |
| 1089 | + } |
| 1090 | + |
| 1091 | + pub fn get_points( |
| 1092 | + env: Env, |
| 1093 | + proxy: Address, |
| 1094 | + storage: Address, |
| 1095 | + subscriber: Address, |
| 1096 | + ) -> u64 { |
| 1097 | + proxy.require_auth(); |
| 1098 | + loyalty::get_eligible_points(&env, &storage, &subscriber) |
| 1099 | + } |
| 1100 | + |
| 1101 | + pub fn get_lifetime_points( |
| 1102 | + env: Env, |
| 1103 | + proxy: Address, |
| 1104 | + storage: Address, |
| 1105 | + subscriber: Address, |
| 1106 | + ) -> u64 { |
| 1107 | + proxy.require_auth(); |
| 1108 | + loyalty::get_lifetime_points(&env, &storage, &subscriber) |
| 1109 | + } |
| 1110 | + |
| 1111 | + pub fn get_streak( |
| 1112 | + env: Env, |
| 1113 | + proxy: Address, |
| 1114 | + storage: Address, |
| 1115 | + subscriber: Address, |
| 1116 | + ) -> u64 { |
| 1117 | + proxy.require_auth(); |
| 1118 | + loyalty::get_streak(&env, &storage, &subscriber) |
| 1119 | + } |
| 1120 | + |
| 1121 | + pub fn get_loyalty_status( |
| 1122 | + env: Env, |
| 1123 | + proxy: Address, |
| 1124 | + storage: Address, |
| 1125 | + subscriber: Address, |
| 1126 | + ) -> (u64, u64, u64, i128, Option<subtrackr_types::LoyaltyTierConfig>) { |
| 1127 | + proxy.require_auth(); |
| 1128 | + let points = loyalty::get_eligible_points(&env, &storage, &subscriber); |
| 1129 | + let lifetime = loyalty::get_lifetime_points(&env, &storage, &subscriber); |
| 1130 | + let streak = loyalty::get_streak(&env, &storage, &subscriber); |
| 1131 | + let spent = loyalty::get_total_spent(&env, &storage, &subscriber); |
| 1132 | + let tier = loyalty::get_current_tier(&env, &storage, &subscriber); |
| 1133 | + (points, lifetime, streak, spent, tier) |
| 1134 | + } |
| 1135 | + |
| 1136 | + pub fn redeem_loyalty_points( |
| 1137 | + env: Env, |
| 1138 | + proxy: Address, |
| 1139 | + storage: Address, |
| 1140 | + subscriber: Address, |
| 1141 | + points: u64, |
| 1142 | + charge_amount: i128, |
| 1143 | + ) -> i128 { |
| 1144 | + proxy.require_auth(); |
| 1145 | + subscriber.require_auth(); |
| 1146 | + let now = env.ledger().timestamp(); |
| 1147 | + loyalty::redeem_points(&env, &storage, &subscriber, points, charge_amount, now) |
| 1148 | + } |
| 1149 | + |
| 1150 | + pub fn earn_referral_bonus( |
| 1151 | + env: Env, |
| 1152 | + proxy: Address, |
| 1153 | + storage: Address, |
| 1154 | + referrer: Address, |
| 1155 | + ) { |
| 1156 | + proxy.require_auth(); |
| 1157 | + let now = env.ledger().timestamp(); |
| 1158 | + loyalty::earn_referral_bonus(&env, &storage, &referrer, now); |
| 1159 | + } |
| 1160 | + |
| 1161 | + pub fn expire_points( |
| 1162 | + env: Env, |
| 1163 | + proxy: Address, |
| 1164 | + storage: Address, |
| 1165 | + subscriber: Address, |
| 1166 | + ) { |
| 1167 | + proxy.require_auth(); |
| 1168 | + get_admin(&env, &storage).require_auth(); |
| 1169 | + loyalty::expire_points(&env, &storage, &subscriber); |
| 1170 | + } |
| 1171 | + |
| 1172 | + pub fn get_point_transactions( |
| 1173 | + env: Env, |
| 1174 | + proxy: Address, |
| 1175 | + storage: Address, |
| 1176 | + subscriber: Address, |
| 1177 | + ) -> Vec<subtrackr_types::PointTransaction> { |
| 1178 | + proxy.require_auth(); |
| 1179 | + loyalty::get_point_transactions(&env, &storage, &subscriber) |
| 1180 | + } |
| 1181 | + |
| 1182 | + pub fn get_redemption( |
| 1183 | + env: Env, |
| 1184 | + proxy: Address, |
| 1185 | + storage: Address, |
| 1186 | + redemption_id: u64, |
| 1187 | + ) -> Option<subtrackr_types::RewardsRedemption> { |
| 1188 | + proxy.require_auth(); |
| 1189 | + loyalty::get_redemption(&env, &storage, redemption_id) |
| 1190 | + } |
| 1191 | + |
1048 | 1192 | // ── Quota & Usage API ── |
1049 | 1193 |
|
1050 | 1194 | pub fn set_plan_quotas( |
|
0 commit comments