Skip to content

Commit 9b2bacb

Browse files
refactoring
1 parent f45bb12 commit 9b2bacb

File tree

7 files changed

+76
-95
lines changed

7 files changed

+76
-95
lines changed

src/extensions/env_extensions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::types;
77
use types::{error::Error, subscription::Subscription};
88
const ADMIN_KEY: &str = "admin";
99
const BASE_FEE: &str = "base_fee";
10-
const LAST_SUBSCRIPTION_ID: &str = "last_subscription_id";
10+
const LAST_SUBSCRIPTION_ID: &str = "last";
1111
const TOKEN_KEY: &str = "token";
1212

1313
pub trait EnvExtensions {

src/lib.rs

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ use soroban_sdk::{
99
Env, Symbol, Vec,
1010
};
1111
use types::{
12-
config_data::ConfigData, create_subscription::CreateSubscription, error::Error,
13-
subscription::Subscription, subscription_status::SubscriptionStatus,
12+
contract_config::ContractConfig, error::Error, subscription::Subscription,
13+
subscription_init_params::SubscriptionInitParams, subscription_status::SubscriptionStatus,
1414
};
1515

16-
const SUBS: Symbol = symbol_short!("SUBS");
16+
const REFLECTOR: Symbol = symbol_short!("reflector");
1717

1818
// 1 day in milliseconds
1919
const DAY: u64 = 86400 * 1000;
@@ -42,7 +42,7 @@ impl SubscriptionContract {
4242
// # Panics
4343
//
4444
// Panics if the contract is already initialized
45-
pub fn config(e: Env, config: ConfigData) {
45+
pub fn config(e: Env, config: ContractConfig) {
4646
config.admin.require_auth();
4747
if e.is_initialized() {
4848
e.panic_with_error(Error::AlreadyInitialized);
@@ -80,8 +80,10 @@ impl SubscriptionContract {
8080
// Panics if the caller doesn't match admin address
8181
pub fn trigger(e: Env, timestamp: u64, trigger_hash: BytesN<32>) {
8282
e.panic_if_not_admin();
83-
e.events()
84-
.publish((SUBS, symbol_short!("trigger")), (timestamp, trigger_hash));
83+
e.events().publish(
84+
(REFLECTOR, symbol_short!("activated")),
85+
(timestamp, trigger_hash),
86+
);
8587
}
8688

8789
// Updates the contract source code. Can be invoked only by the admin account.
@@ -113,10 +115,10 @@ impl SubscriptionContract {
113115
let mut total_charge: u64 = 0;
114116
let now = now(&e);
115117
let fee = e.get_fee();
116-
let mut deactivated_subscriptions = Vec::new(&e);
118+
let mut events = Vec::new(&e);
117119
for subscription_id in subscription_ids.iter() {
118120
if let Some(mut subscription) = e.get_subscription(subscription_id) {
119-
let days = (now - subscription.last_charge) / DAY;
121+
let days = (now - subscription.updated) / DAY;
120122
if days == 0 {
121123
continue;
122124
}
@@ -125,30 +127,39 @@ impl SubscriptionContract {
125127
charge = subscription.balance;
126128
}
127129
subscription.balance -= charge;
128-
subscription.last_charge = now;
130+
subscription.updated = now;
129131
if subscription.balance < fee {
130132
// Deactivate the subscription if the balance is less than the fee
131133
subscription.status = SubscriptionStatus::Suspended;
132-
deactivated_subscriptions.push_back(subscription_id);
134+
events.push_back((
135+
(
136+
REFLECTOR,
137+
symbol_short!("suspended"),
138+
subscription.owner.clone(),
139+
),
140+
(now, subscription_id),
141+
));
133142
}
134143
e.set_subscription(subscription_id, &subscription);
135144

145+
events.push_back((
146+
(
147+
REFLECTOR,
148+
symbol_short!("charged"),
149+
subscription.owner,
150+
),
151+
(now, subscription_id),
152+
));
153+
136154
total_charge += charge;
137155
}
138156
}
139157
// If there is nothing to charge, return
140158
if total_charge == 0 {
141159
return;
142160
}
143-
//Publish the events
144-
e.events()
145-
.publish((SUBS, symbol_short!("charged")), (now, subscription_ids));
146-
147-
if !deactivated_subscriptions.is_empty() {
148-
e.events().publish(
149-
(SUBS, symbol_short!("suspended")),
150-
deactivated_subscriptions,
151-
);
161+
for (event, data) in events.iter() {
162+
e.events().publish(event, data);
152163
}
153164

154165
//Burn the tokens
@@ -177,15 +188,15 @@ impl SubscriptionContract {
177188
// Panics if the subscription is invalid
178189
pub fn create_subscription(
179190
e: Env,
180-
new_subscription: CreateSubscription,
191+
new_subscription: SubscriptionInitParams,
181192
amount: u64,
182193
) -> (u64, Subscription) {
183-
panin_if_not_initialized(&e);
194+
panic_if_not_initialized(&e);
184195
// Check the authorization
185196
new_subscription.owner.require_auth();
186197

187198
// Check the amount
188-
let activation_fee = get_activation_fee(&e);
199+
let activation_fee = e.get_fee() * MIN_FEE_FACTOR;
189200
if amount < activation_fee {
190201
e.panic_with_error(Error::InvalidAmount);
191202
}
@@ -194,7 +205,7 @@ impl SubscriptionContract {
194205
e.panic_with_error(Error::InvalidHeartbeat);
195206
}
196207

197-
if new_subscription.threshold == 0 {
208+
if new_subscription.threshold == 0 || new_subscription.threshold > 1000 {
198209
e.panic_with_error(Error::InvalidThreshold);
199210
}
200211

@@ -209,20 +220,20 @@ impl SubscriptionContract {
209220
let subscription_id = e.get_last_subscription_id() + 1;
210221
let subscription = Subscription {
211222
owner: new_subscription.owner,
212-
asset1: new_subscription.asset1,
213-
asset2: new_subscription.asset2,
223+
base: new_subscription.base,
224+
quote: new_subscription.quote,
214225
threshold: new_subscription.threshold,
215226
heartbeat: new_subscription.heartbeat,
216227
webhook: new_subscription.webhook,
217228
balance: amount - activation_fee,
218229
status: SubscriptionStatus::Active,
219-
last_charge: now(&e), // normalize to milliseconds
230+
updated: now(&e), // normalize to milliseconds
220231
};
221232
e.set_subscription(subscription_id, &subscription);
222233
e.set_last_subscription_id(subscription_id);
223-
let data = (subscription_id, subscription);
234+
let data = (subscription_id, subscription.clone());
224235
e.events()
225-
.publish((SUBS, symbol_short!("created")), data.clone());
236+
.publish((REFLECTOR, symbol_short!("created"), subscription.owner), data.clone());
226237
return data;
227238
}
228239

@@ -241,25 +252,24 @@ impl SubscriptionContract {
241252
// Panics if the subscription does not exist
242253
// Panics if the token transfer fails
243254
pub fn deposit(e: Env, from: Address, subscription_id: u64, amount: u64) {
244-
panin_if_not_initialized(&e);
255+
panic_if_not_initialized(&e);
245256
from.require_auth();
246257
if amount == 0 {
247258
e.panic_with_error(Error::InvalidAmount);
248259
}
249260
let mut subscription = e
250261
.get_subscription(subscription_id)
251262
.unwrap_or_else(|| panic_with_error!(e, Error::SubscriptionNotFound));
252-
let activation_fee = get_activation_fee(&e);
253263
let mut burn_amount = 0;
254-
264+
let fee = e.get_fee();
255265
match subscription.status {
256266
SubscriptionStatus::Suspended => {
257267
// Check if the subscription is suspended
258-
if amount < activation_fee {
268+
if amount < fee {
259269
e.panic_with_error(Error::InvalidAmount);
260270
}
261271
// Set the activation fee as the burn amount
262-
burn_amount = activation_fee;
272+
burn_amount = fee;
263273
subscription.status = SubscriptionStatus::Active;
264274
}
265275
SubscriptionStatus::Cancelled => {
@@ -273,8 +283,10 @@ impl SubscriptionContract {
273283

274284
subscription.balance += amount - burn_amount;
275285
e.set_subscription(subscription_id, &subscription);
276-
e.events()
277-
.publish((SUBS, symbol_short!("deposit")), (subscription_id, amount));
286+
e.events().publish(
287+
(REFLECTOR, symbol_short!("deposited"), subscription.owner.clone()),
288+
(subscription_id, subscription, amount),
289+
);
278290
}
279291

280292
// Withdraws funds from the subscription and deactivates it.
@@ -288,7 +300,7 @@ impl SubscriptionContract {
288300
// # Panics if the subscription is not active
289301
// # Panics if the token transfer fails
290302
pub fn cancel(e: Env, subscription_id: u64) {
291-
panin_if_not_initialized(&e);
303+
panic_if_not_initialized(&e);
292304
let mut subscription = e
293305
.get_subscription(subscription_id)
294306
.unwrap_or_else(|| panic_with_error!(e, Error::SubscriptionNotFound));
@@ -310,7 +322,7 @@ impl SubscriptionContract {
310322
subscription.balance = 0;
311323
e.set_subscription(subscription_id, &subscription);
312324
e.events()
313-
.publish((SUBS, symbol_short!("cancelled")), subscription_id);
325+
.publish((REFLECTOR, symbol_short!("cancelled"), subscription.owner), subscription_id);
314326
}
315327

316328
// Gets the subscription by ID.
@@ -327,7 +339,7 @@ impl SubscriptionContract {
327339
//
328340
// Panics if the contract is not initialized
329341
pub fn get_subscription(e: Env, subscription_id: u64) -> Subscription {
330-
panin_if_not_initialized(&e);
342+
panic_if_not_initialized(&e);
331343
e.get_subscription(subscription_id)
332344
.unwrap_or_else(|| panic_with_error!(e, Error::SubscriptionNotFound))
333345
}
@@ -361,7 +373,7 @@ impl SubscriptionContract {
361373
//
362374
// Base fee
363375
pub fn fee(e: Env) -> u64 {
364-
panin_if_not_initialized(&e);
376+
panic_if_not_initialized(&e);
365377
e.get_fee()
366378
}
367379

@@ -371,12 +383,12 @@ impl SubscriptionContract {
371383
//
372384
// Token address
373385
pub fn token(e: Env) -> Address {
374-
panin_if_not_initialized(&e);
386+
panic_if_not_initialized(&e);
375387
e.get_token()
376388
}
377389
}
378390

379-
fn panin_if_not_initialized(e: &Env) {
391+
fn panic_if_not_initialized(e: &Env) {
380392
if !e.is_initialized() {
381393
panic_with_error!(e, Error::NotInitialized);
382394
}
@@ -386,10 +398,6 @@ fn get_token_client(e: &Env) -> TokenClient {
386398
TokenClient::new(e, &e.get_token())
387399
}
388400

389-
fn get_activation_fee(e: &Env) -> u64 {
390-
e.get_fee() * MIN_FEE_FACTOR
391-
}
392-
393401
fn transfer_tokens_to_current_contract(e: &Env, from: &Address, amount: u64, burn_amount: u64) {
394402
transfer_tokens(e, from, &e.current_contract_address(), amount);
395403
if burn_amount > 0 {

src/test.rs

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
use super::*;
44
use soroban_sdk::{
5-
symbol_short, testutils::{Address as _, Events, Ledger, LedgerInfo}, token::StellarAssetClient, vec, Bytes, Env, IntoVal, String
5+
symbol_short, testutils::{Address as _, Ledger, LedgerInfo}, token::StellarAssetClient, vec, Bytes, Env, String
66
};
77
use types::{
8-
asset::Asset, config_data::ConfigData, create_subscription::CreateSubscription,
8+
asset::Asset, contract_config::ContractConfig, subscription_init_params::SubscriptionInitParams,
99
ticker_asset::TickerAsset,
1010
};
1111

12-
fn init_contract_with_admin<'a>() -> (Env, SubscriptionContractClient<'a>, ConfigData) {
12+
fn init_contract_with_admin<'a>() -> (Env, SubscriptionContractClient<'a>, ContractConfig) {
1313
let env = Env::default();
1414

1515
let admin = Address::generate(&env);
@@ -20,7 +20,7 @@ fn init_contract_with_admin<'a>() -> (Env, SubscriptionContractClient<'a>, Confi
2020

2121
let token = env.register_stellar_asset_contract(admin.clone());
2222

23-
let init_data = ConfigData {
23+
let init_data = ContractConfig {
2424
admin: admin.clone(),
2525
token,
2626
fee: 100,
@@ -43,13 +43,13 @@ fn test() {
4343
let token_client = StellarAssetClient::new(&env, &config.token);
4444
token_client.mint(&owner, &1000);
4545

46-
let subscription = CreateSubscription {
46+
let subscription = SubscriptionInitParams {
4747
owner: owner.clone(),
48-
asset1: TickerAsset {
48+
base: TickerAsset {
4949
asset: Asset::Other(symbol_short!("BTC")),
5050
source: String::from_str(&env, "source1"),
5151
},
52-
asset2: TickerAsset {
52+
quote: TickerAsset {
5353
asset: Asset::Other(symbol_short!("ETH")),
5454
source: String::from_str(&env, "source2"),
5555
},
@@ -59,42 +59,15 @@ fn test() {
5959
};
6060

6161
// create subscription
62-
let (subscription_id, data) = client.create_subscription(&subscription, &200);
62+
let (subscription_id, _) = client.create_subscription(&subscription, &200);
6363
assert!(subscription_id == 1);
6464

65-
let mut event = (
66-
client.address.clone(),
67-
(symbol_short!("SUBS"), symbol_short!("created")).into_val(&env),
68-
(1u64, data).into_val(&env),
69-
);
70-
assert_eq!(
71-
vec![&env, env.events().all().last().unwrap()],
72-
vec![&env, event]
73-
);
74-
7565
let trigger_hash: BytesN<32> = BytesN::from_array(&env, &[0; 32]);
7666
// heartbeat subscription
7767
client.trigger(&1u64, &trigger_hash);
78-
event = (
79-
client.address.clone(),
80-
(symbol_short!("SUBS"), symbol_short!("trigger")).into_val(&env),
81-
(1u64, trigger_hash).into_val(&env),
82-
);
83-
84-
let trigger_event = vec![&env, env.events().all().last().unwrap()];
85-
assert_eq!(trigger_event, vec![&env, event]);
8668

8769
// deposit subscription
8870
client.deposit(&owner, &1, &100);
89-
event = (
90-
client.address.clone(),
91-
(symbol_short!("SUBS"), symbol_short!("deposit")).into_val(&env),
92-
(1u64, 100u64).into_val(&env),
93-
);
94-
assert_eq!(
95-
vec![&env, env.events().all().last().unwrap()],
96-
vec![&env, event]
97-
);
9871

9972
let mut subs = client.get_subscription(&subscription_id);
10073
assert_eq!(subs.balance, 200);
@@ -112,7 +85,7 @@ fn test() {
11285
subs = client.get_subscription(&subscription_id);
11386
assert_eq!(subs.balance, 0);
11487
assert_eq!(subs.status, SubscriptionStatus::Suspended);
115-
assert_eq!(subs.last_charge, 86400 * 2 * 1000);
88+
assert_eq!(subs.updated, 86400 * 2 * 1000);
11689

11790
// deposit subscription to renew
11891
client.deposit(&owner, &1, &200);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use soroban_sdk::{contracttype, Address};
44
#[derive(Clone, Debug, Eq, PartialEq)]
55

66
// The configuration parameters for the contract.
7-
pub struct ConfigData {
7+
pub struct ContractConfig {
88
// The admin address.
99
pub admin: Address,
1010
// The base asset for the prices.

src/types/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ pub mod asset;
22
pub mod ticker_asset;
33
pub mod subscription;
44
pub mod error;
5-
pub mod config_data;
6-
pub mod create_subscription;
5+
pub mod contract_config;
6+
pub mod subscription_init_params;
77
pub mod subscription_status;

0 commit comments

Comments
 (0)