Skip to content

Commit 4396942

Browse files
Merge pull request #87 from Samaro1/feat/free-to-paid-tier-event
feat(events): emit free-to-paid tier transition event
2 parents ae48129 + b95ea10 commit 4396942

2 files changed

Lines changed: 60 additions & 3 deletions

File tree

contracts/substream_contracts/src/lib.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![no_std]
22
use soroban_sdk::token::Client as TokenClient;
3-
use soroban_sdk::{contract, contractevent, contractimpl, contracttype, vec, Address, Bytes, Env, Vec};
3+
use soroban_sdk::{contract, contractevent, contractimpl, contracttype, vec, Address, Env, Vec};
44

55
// --- Constants ---
66
const MINIMUM_FLOW_DURATION: u64 = 86400;
@@ -72,6 +72,7 @@ pub struct Subscription {
7272
pub last_collected: u64,
7373
pub start_time: u64,
7474
pub last_funds_exhausted: u64,
75+
pub free_to_paid_emitted: bool,
7576
pub creators: Vec<Address>,
7677
pub percentages: Vec<u32>,
7778
pub payer: Address,
@@ -94,6 +95,14 @@ pub struct TierChanged {
9495
pub new_rate: i128,
9596
}
9697

98+
#[contractevent]
99+
pub struct FreeToPaidTierActivated {
100+
#[topic] pub subscriber: Address,
101+
#[topic] pub creator: Address,
102+
pub rate_per_second: i128,
103+
pub activated_at: u64,
104+
}
105+
97106
#[contractevent]
98107
pub struct Subscribed {
99108
#[topic] pub subscriber: Address,
@@ -330,6 +339,19 @@ fn distribute_and_collect(env: &Env, beneficiary: &Address, stream_id: &Address,
330339
let now = env.ledger().timestamp();
331340

332341
if now <= sub.last_collected { return 0; }
342+
343+
let trial_end = sub.start_time.saturating_add(sub.tier.trial_duration);
344+
if !sub.free_to_paid_emitted && sub.tier.rate_per_second > 0 && now > trial_end {
345+
FreeToPaidTierActivated {
346+
subscriber: beneficiary.clone(),
347+
creator: stream_id.clone(),
348+
rate_per_second: sub.tier.rate_per_second,
349+
activated_at: now,
350+
}
351+
.publish(env);
352+
sub.free_to_paid_emitted = true;
353+
}
354+
333355
if let Some(creator) = total_streamed_creator {
334356
if is_creator_paused(env, creator) {
335357
sub.last_collected = now;
@@ -338,11 +360,10 @@ fn distribute_and_collect(env: &Env, beneficiary: &Address, stream_id: &Address,
338360
}
339361
}
340362

341-
let trial_end = sub.start_time.saturating_add(sub.tier.trial_duration);
342363
let charge_start = if sub.last_collected > trial_end { sub.last_collected } else { trial_end };
343364
if now <= charge_start { return 0; }
344365

345-
let mut amount_to_collect = calculate_discounted_charge(sub.start_time, charge_start, now, sub.tier.rate_per_second);
366+
let amount_to_collect = calculate_discounted_charge(sub.start_time, charge_start, now, sub.tier.rate_per_second);
346367

347368
// Check if grace period is active or expired
348369
if sub.balance <= 0 && sub.last_funds_exhausted > 0 {
@@ -436,6 +457,7 @@ fn subscribe_core(env: &Env, payer: &Address, beneficiary: &Address, stream_id:
436457
last_collected: now,
437458
start_time: now,
438459
last_funds_exhausted: 0,
460+
free_to_paid_emitted: false,
439461
creators,
440462
percentages,
441463
payer: payer.clone(),

contracts/substream_contracts/src/test.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use super::*;
44
use soroban_sdk::{
55
testutils::{Address as _, Ledger},
6+
testutils::Events as _,
67
token, vec, Address, Env,
78
};
89

@@ -14,6 +15,11 @@ fn create_token_contract<'a>(env: &Env, admin: &Address) -> token::Client<'a> {
1415
token::Client::new(env, &sac.address())
1516
}
1617

18+
fn last_call_contract_event_count(env: &Env, contract_id: &Address) -> usize {
19+
let events = env.events().all().filter_by_contract(contract_id);
20+
events.events().len()
21+
}
22+
1723
// ---------------------------------------------------------------------------
1824
// is_subscribed
1925
// ---------------------------------------------------------------------------
@@ -111,6 +117,35 @@ fn test_free_trial_ignores_claims_within_first_week() {
111117
assert_eq!(token.balance(&creator), 27);
112118
}
113119

120+
#[test]
121+
fn test_free_to_paid_transition_event_emitted_once() {
122+
let env = Env::default();
123+
env.mock_all_auths();
124+
125+
let subscriber = Address::generate(&env);
126+
let creator = Address::generate(&env);
127+
let admin = Address::generate(&env);
128+
129+
let token = create_token_contract(&env, &admin);
130+
let token_admin = token::StellarAssetClient::new(&env, &token.address);
131+
token_admin.mint(&subscriber, &1000);
132+
133+
let contract_id = env.register(SubStreamContract, ());
134+
let client = SubStreamContractClient::new(&env, &contract_id);
135+
136+
let start = 100u64;
137+
env.ledger().set_timestamp(start);
138+
client.subscribe(&subscriber, &creator, &token.address, &300, &1);
139+
140+
env.ledger().set_timestamp(start + WEEK + 1);
141+
client.collect(&subscriber, &creator);
142+
assert_eq!(last_call_contract_event_count(&env, &contract_id), 1);
143+
144+
env.ledger().set_timestamp(start + WEEK + 10);
145+
client.collect(&subscriber, &creator);
146+
assert_eq!(last_call_contract_event_count(&env, &contract_id), 0);
147+
}
148+
114149
// ---------------------------------------------------------------------------
115150
// Cancel
116151
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)