Skip to content

Commit

Permalink
Implement streak insurance
Browse files Browse the repository at this point in the history
  • Loading branch information
hpeebles committed Dec 11, 2024
1 parent 5fe3268 commit 8d05983
Show file tree
Hide file tree
Showing 26 changed files with 506 additions and 46 deletions.
4 changes: 3 additions & 1 deletion backend/canisters/local_user_index/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use types::{
CanisterId, ChannelLatestMessageIndex, ChatId, ChitEarnedReason, CommunityId, Cryptocurrency,
DiamondMembershipPlanDuration, MessageContent, MessageContentInitial, MessageId, MessageIndex, NotifyChit, PhoneNumber,
ReferralType, SlashCommandSchema, SuspensionDuration, TimestampMillis, UniquePersonProof, UpdateUserPrincipalArgs, User,
UserId, UserType,
UserCanisterStreakInsuranceClaim, UserCanisterStreakInsurancePayment, UserId, UserType,
};

mod lifecycle;
Expand Down Expand Up @@ -202,6 +202,8 @@ pub struct ExternalAchievementAwarded {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum UserEvent {
NotifyChit(NotifyChit),
NotifyStreakInsurancePayment(UserCanisterStreakInsurancePayment),
NotifyStreakInsuranceClaim(UserCanisterStreakInsuranceClaim),
}

#[derive(CandidType, Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use canister_api_macros::update;
use canister_tracing_macros::trace;
use local_user_index_canister::c2c_notify_user_events::{Response::*, *};
use local_user_index_canister::UserEvent;
use types::UserId;
use types::{StreakInsuranceClaim, StreakInsurancePayment, UserId};

#[update(guard = "caller_is_local_user_canister", msgpack = true)]
#[trace]
Expand All @@ -25,5 +25,25 @@ fn handle_event(user_id: UserId, event: UserEvent, state: &mut RuntimeState) {
UserEvent::NotifyChit(ev) => {
state.push_event_to_user_index(UserIndexEvent::NotifyChit(Box::new((user_id, ev))));
}
UserEvent::NotifyStreakInsurancePayment(payment) => {
state.push_event_to_user_index(UserIndexEvent::NotifyStreakInsurancePayment(Box::new(
StreakInsurancePayment {
user_id,
timestamp: payment.timestamp,
chat_amount: payment.chat_amount,
additional_days: payment.additional_days,
new_days_insured: payment.new_days_insured,
transaction_index: payment.transaction_index,
},
)));
}
UserEvent::NotifyStreakInsuranceClaim(claim) => {
state.push_event_to_user_index(UserIndexEvent::NotifyStreakInsuranceClaim(Box::new(StreakInsuranceClaim {
user_id,
timestamp: claim.timestamp,
streak_length: claim.streak_length,
new_days_claimed: claim.new_days_claimed,
})));
}
}
}
5 changes: 3 additions & 2 deletions backend/canisters/user/api/src/queries/initial_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use candid::CandidType;
use serde::{Deserialize, Serialize};
use ts_export::ts_export;
use types::{
CanisterId, Chat, ChatId, ChitEarned, DirectChatSummary, Empty, GroupChatSummary, PinNumberSettings, TimestampMillis,
UserId,
CanisterId, Chat, ChatId, ChitEarned, DirectChatSummary, Empty, GroupChatSummary, PinNumberSettings, StreakInsurance,
TimestampMillis, UserId,
};

pub type Args = Empty;
Expand Down Expand Up @@ -34,6 +34,7 @@ pub struct SuccessResult {
pub chit_balance: i32,
pub streak: u16,
pub streak_ends: TimestampMillis,
pub streak_insurance: Option<StreakInsurance>,
pub next_daily_claim: TimestampMillis,
pub is_unique_person: bool,
pub wallet_config: WalletConfig,
Expand Down
4 changes: 3 additions & 1 deletion backend/canisters/user/api/src/queries/updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use ts_export::ts_export;
use types::{
Chat, ChatId, ChitEarned, CommunityId, DirectChatSummary, DirectChatSummaryUpdates, OptionUpdate, PinNumberSettings,
TimestampMillis, UserId,
StreakInsurance, TimestampMillis, UserId,
};

#[ts_export(user, updates)]
Expand Down Expand Up @@ -44,6 +44,8 @@ pub struct SuccessResult {
pub chit_balance: i32,
pub streak: u16,
pub streak_ends: TimestampMillis,
#[ts(as = "types::OptionUpdateStreakInsurance")]
pub streak_insurance: OptionUpdate<StreakInsurance>,
pub next_daily_claim: TimestampMillis,
pub is_unique_person: Option<bool>,
pub wallet_config: Option<WalletConfig>,
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/user/api/src/updates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub mod mark_achievements_seen;
pub mod mark_message_activity_feed_read;
pub mod mark_read;
pub mod mute_notifications;
pub mod pay_for_streak_insurance;
pub mod pin_chat_v2;
pub mod reclaim_swap_tokens;
pub mod remove_reaction;
Expand Down
20 changes: 20 additions & 0 deletions backend/canisters/user/api/src/updates/pay_for_streak_insurance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use candid::CandidType;
use serde::{Deserialize, Serialize};
use ts_export::ts_export;

#[ts_export(user, pay_for_streak_insurance)]
#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub additional_days: u8,
pub expected_price: u128,
}

#[ts_export(user, pay_for_streak_insurance)]
#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
IncorrectPrice(u128),
PaymentAlreadyInProgress,
PaymentFailed(String),
InternalError(String),
}
53 changes: 41 additions & 12 deletions backend/canisters/user/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ use candid::Principal;
use canister_state_macros::canister_state;
use canister_timer_jobs::TimerJobs;
use constants::{DAY_IN_MS, MINUTE_IN_MS, OPENCHAT_BOT_USER_ID};
use event_store_producer::{EventStoreClient, EventStoreClientBuilder, EventStoreClientInfo};
use event_store_producer::{EventBuilder, EventStoreClient, EventStoreClientBuilder, EventStoreClientInfo};
use event_store_producer_cdk_runtime::CdkRuntime;
use fire_and_forget_handler::FireAndForgetHandler;
use local_user_index_canister::UserEvent as LocalUserIndexEvent;
use model::chit::ChitEarnedEvents;
use model::chit_earned_events::ChitEarnedEvents;
use model::contacts::Contacts;
use model::favourite_chats::FavouriteChats;
use model::message_activity_events::MessageActivityEvents;
Expand All @@ -36,7 +36,7 @@ use timer_job_queues::GroupedTimerJobQueue;
use types::{
Achievement, BuildVersion, CanisterId, Chat, ChatId, ChatMetrics, ChitEarned, ChitEarnedReason, CommunityId,
Cryptocurrency, Cycles, Document, Milliseconds, Notification, NotifyChit, TimestampMillis, Timestamped, UniquePersonProof,
UserId,
UserCanisterStreakInsuranceClaim, UserCanisterStreakInsurancePayment, UserId,
};
use user_canister::{MessageActivityEvent, NamedAccount, UserCanisterEvent, WalletConfig};
use utils::env::Environment;
Expand Down Expand Up @@ -153,6 +153,33 @@ impl RuntimeState {
}
}

pub fn mark_streak_insurance_payment(&mut self, payment: UserCanisterStreakInsurancePayment) {
let user_id: UserId = self.env.canister_id().into();
self.data.streak.mark_streak_insurance_payment(payment.clone());
self.data.event_store_client.push(
EventBuilder::new("user_streak_insurance_payment", payment.timestamp)
.with_user(user_id.to_string(), true)
.with_source(user_id.to_string(), true)
.with_json_payload(&payment)
.build(),
);
self.data
.push_local_user_index_canister_event(LocalUserIndexEvent::NotifyStreakInsurancePayment(payment));
}

pub fn mark_streak_insurance_claim(&mut self, claim: UserCanisterStreakInsuranceClaim) {
let user_id: UserId = self.env.canister_id().into();
self.data.event_store_client.push(
EventBuilder::new("user_streak_insurance_claim", claim.timestamp)
.with_user(user_id.to_string(), true)
.with_source(user_id.to_string(), true)
.with_json_payload(&claim)
.build(),
);
self.data
.push_local_user_index_canister_event(LocalUserIndexEvent::NotifyStreakInsuranceClaim(claim));
}

pub fn is_empty_and_dormant(&self) -> bool {
if self.data.direct_chats.len() <= 1
&& self.data.group_chats.len() == 0
Expand Down Expand Up @@ -425,16 +452,18 @@ impl Data {
}
}

pub fn push_local_user_index_canister_event(&mut self, event: LocalUserIndexEvent) {
self.local_user_index_event_sync_queue
.push(self.local_user_index_canister_id, event);
}

pub fn notify_user_index_of_chit(&mut self, now: TimestampMillis) {
self.local_user_index_event_sync_queue.push(
self.local_user_index_canister_id,
LocalUserIndexEvent::NotifyChit(NotifyChit {
timestamp: now,
chit_balance: self.chit_events.balance_for_month_by_timestamp(now),
streak: self.streak.days(now),
streak_ends: self.streak.ends(),
}),
);
self.push_local_user_index_canister_event(LocalUserIndexEvent::NotifyChit(NotifyChit {
timestamp: now,
chit_balance: self.chit_events.balance_for_month_by_timestamp(now),
streak: self.streak.days(now),
streak_ends: self.streak.ends(),
}))
}

pub fn push_message_activity(&mut self, event: MessageActivityEvent, now: TimestampMillis) {
Expand Down
2 changes: 1 addition & 1 deletion backend/canisters/user/impl/src/model/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod chit;
pub mod chit_earned_events;
pub mod communities;
pub mod community;
pub mod contacts;
Expand Down
Loading

0 comments on commit 8d05983

Please sign in to comment.