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
1 change: 1 addition & 0 deletions contract/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub enum ContractError {
/// Returned when the batch size exceeds the maximum allowed
BatchTooLarge = 20,
/// Returned when a merchant attempts to withdraw with no accrued revenue
SubscriptionAlreadyActive = 21,
ZeroBalanceAvailable = 21,
/// Returned when attempting to subscribe to a frozen merchant
MerchantFrozen = 22,
Expand Down
136 changes: 119 additions & 17 deletions contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,68 @@ impl FlowPay {
trial_period: Option<u64>,
referrer: Option<Address>,
) {
subscribe_inner(
&env,
user,
merchant,
ensure_contract_not_paused(&env);
user.require_auth();

if whitelist::is_whitelist_enabled(&env) {
if !whitelist::is_whitelisted(&env, &merchant) {
env.panic_with_error(ContractError::MerchantNotWhitelisted);
}
}

if whitelist::is_frozen(&env, &merchant) {
env.panic_with_error(ContractError::MerchantFrozen);
}
if interval < 60 {
env.panic_with_error(ContractError::IntervalMustBePositive);
}

use soroban_sdk::xdr::ToXdr;
if token.clone().to_xdr(&env).get(7) == Some(0) {
env.panic_with_error(ContractError::InvalidTokenAddress);
}

validation::check_allowance(&env, &user, &token, amount);
if interval < 60 {
env.panic_with_error(ContractError::IntervalTooShort);
}

if interval < min_interval::get_min_interval(&env) {
env.panic_with_error(ContractError::IntervalTooShort);
}

let token_client = token::Client::new(&env, &token);
let allowance = token_client.allowance(&user, &env.current_contract_address());
if allowance < amount {
env.panic_with_error(ContractError::InsufficientAllowance);
}

let now = env.ledger().timestamp();
let trial_duration = trial_period.unwrap_or(0);
let last_charged = now + trial_duration;

let existing = storage::get_subscription(&env, &user);
let should_increment = existing.as_ref().map_or(true, |s| !s.active);

let sub = Subscription {
merchant: merchant.clone(),
amount,
interval,
token,
trial_period,
referrer,
);
last_charged,
active: true,
paused: false,
token: token.clone(),
referrer: referrer.clone(),
label: Symbol::new(&env, "default"),
trial_duration,
};

env.storage()
.persistent()
.set(&DataKey::Subscription(user.clone()), &sub);

extend_subscription_ttl(&env, &user);
subscribe_inner(&env, user.clone(), merchant.clone(), amount, interval, token.clone(), trial_period, referrer.clone());
}
Comment thread
orunganiekan marked this conversation as resolved.

pub fn subscribe_with_metadata(
Expand All @@ -278,19 +330,69 @@ impl FlowPay {
if label.len() > 64 {
env.panic_with_error(ContractError::MetadataLabelTooLong);
}
subscribe_inner(&env, user.clone(), merchant.clone(), amount, interval, token.clone(), trial_period, referrer.clone());
subscription_metadata::set_metadata(&env, &user, label.clone());

if whitelist::is_frozen(&env, &merchant) {
env.panic_with_error(ContractError::MerchantFrozen);
}

validation::require_valid_amount(&env, amount);
if interval == 0 {
env.panic_with_error(ContractError::IntervalMustBePositive);
}

use soroban_sdk::xdr::ToXdr;
if token.clone().to_xdr(&env).get(7) == Some(0) {
env.panic_with_error(ContractError::InvalidTokenAddress);
}

validation::check_allowance(&env, &user, &token, amount);

if interval < min_interval::get_min_interval(&env) {
env.panic_with_error(ContractError::IntervalTooShort);
}

let token_client = token::Client::new(&env, &token);
let allowance = token_client.allowance(&user, &env.current_contract_address());
if allowance < amount {
env.panic_with_error(ContractError::InsufficientAllowance);
}

let now = env.ledger().timestamp();
let trial_duration = trial_period.unwrap_or(0);
let last_charged = now + trial_duration;

subscribe_inner(
&env,
user.clone(),
merchant,
let existing = storage::get_subscription(&env, &user);
let should_increment = existing.as_ref().map_or(true, |s| !s.active);

let sub = Subscription {
merchant: merchant.clone(),
amount,
interval,
token,
trial_period,
referrer,
);
last_charged,
active: true,
paused: false,
token: token.clone(),
referrer: referrer.clone(),
label: Symbol::new(&env, ""), // deprecated: use SubscriptionMeta storage instead
trial_duration,
};

let _ = subscription_metadata::set_metadata(&env, &user, label);
env.storage()
.persistent()
.set(&DataKey::Subscription(user.clone()), &sub);

extend_subscription_ttl(&env, &user);

if should_increment {
subscription_count::increment(&env);
subscription_count::append_subscriber_index(&env, &user);
}
referral::store_referral(&env, &user, &referrer);
merchant_stats::increment_subscriber_count(&env, &sub.merchant);
events::publish_subscribed(&env, &user, &sub);
let _ = subscription_metadata::set_metadata(&env, &user, label.clone());
}

/// Charges the next due recurring payment for `user`.
Expand Down
Loading