use crate::{
mock::*,
types::{PaymentDetail, PaymentState},
weights::WeightInfo,
Payment as PaymentStore, PaymentHandler, ScheduledTask, ScheduledTasks, Task,
};
use frame_support::{assert_noop, assert_ok, storage::with_transaction, traits::OnIdle, weights::Weight};
use orml_traits::MultiCurrency;
use sp_runtime::{Percent, TransactionOutcome};
type Error = crate::Error<Test>;
fn last_event() -> RuntimeEvent {
System::events().pop().expect("Event expected").event
}
#[test]
fn test_pay_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentCreated {
from: PAYMENT_CREATOR,
asset: CURRENCY_ID,
amount: payment_amount,
remark: None
}
.into()
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_incentive_amount
);
assert_eq!(
Tokens::total_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(Tokens::total_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_noop!(
Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
),
crate::Error::<Test>::PaymentAlreadyInProcess
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: 2,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
});
}
#[test]
fn test_cancel_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_incentive_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(Payment::cancel(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR
));
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentCancelled {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT
}
.into()
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
});
}
#[test]
fn test_release_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_incentive_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(Payment::release(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentReleased {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT
}
.into()
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - (payment_amount * 2) - expected_incentive_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
});
}
#[test]
fn test_resolve_payment_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_noop!(
Payment::resolve_payment(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_CREATOR,
PAYMENT_RECIPENT,
Percent::from_percent(100)
),
Error::InvalidAction
);
assert_ok!(Payment::resolve_payment(
RuntimeOrigin::signed(RESOLVER_ACCOUNT),
PAYMENT_CREATOR,
PAYMENT_RECIPENT,
Percent::from_percent(100)
));
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentResolved {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
recipient_share: Percent::from_percent(100)
}
.into()
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(Payment::resolve_payment(
RuntimeOrigin::signed(RESOLVER_ACCOUNT),
PAYMENT_CREATOR,
PAYMENT_RECIPENT,
Percent::from_percent(0)
));
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentResolved {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
recipient_share: Percent::from_percent(0)
}
.into()
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
});
}
#[test]
fn test_charging_fee_payment_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_fee_amount = payment_amount / MARKETPLACE_FEE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_fee_amount - expected_incentive_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED), 0);
assert_ok!(Payment::release(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED
));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_fee_amount
);
assert_eq!(
Tokens::total_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_fee_amount
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED),
payment_amount
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &FEE_RECIPIENT_ACCOUNT),
expected_fee_amount
);
});
}
#[test]
fn test_charging_fee_payment_works_when_canceled() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_fee_amount = payment_amount / MARKETPLACE_FEE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED,
CURRENCY_ID,
payment_amount,
None
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_fee_amount - expected_incentive_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED), 0);
assert_ok!(Payment::cancel(
RuntimeOrigin::signed(PAYMENT_RECIPENT_FEE_CHARGED),
PAYMENT_CREATOR
));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::total_balance(CURRENCY_ID, &PAYMENT_CREATOR), 100);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED), 0);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &FEE_RECIPIENT_ACCOUNT), 0);
});
}
#[test]
fn test_pay_with_remark_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
Some(vec![1u8; 10].try_into().unwrap())
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_incentive_amount
);
assert_eq!(
Tokens::total_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(Tokens::total_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_noop!(
Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
),
crate::Error::<Test>::PaymentAlreadyInProcess
);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentCreated {
from: PAYMENT_CREATOR,
asset: CURRENCY_ID,
amount: payment_amount,
remark: Some(vec![1u8; 10].try_into().unwrap())
}
.into()
);
});
}
#[test]
fn test_do_not_overwrite_logic_works() {
new_test_ext().execute_with(|| {
let payment_amount = 40;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_noop!(
Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
),
crate::Error::<Test>::PaymentAlreadyInProcess
);
PaymentStore::<Test>::insert(
PAYMENT_CREATOR,
PAYMENT_RECIPENT,
PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::NeedsReview,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
},
);
assert_noop!(
Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
),
crate::Error::<Test>::PaymentAlreadyInProcess
);
});
}
#[test]
fn test_request_refund() {
new_test_ext().execute_with(|| {
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_cancel_block = CANCEL_BLOCK_BUFFER + 1;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
assert_noop!(
Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
),
crate::Error::<Test>::PaymentAlreadyInProcess
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::RefundRequested {
cancel_block: expected_cancel_block
},
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentCreatorRequestedRefund {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
expiry: expected_cancel_block
}
.into()
);
});
}
#[test]
fn test_dispute_refund() {
new_test_ext().execute_with(|| {
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_cancel_block = CANCEL_BLOCK_BUFFER + 1;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_noop!(
Payment::dispute_refund(RuntimeOrigin::signed(PAYMENT_RECIPENT), PAYMENT_CREATOR),
Error::InvalidAction
);
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(
scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)).unwrap(),
&ScheduledTask {
task: Task::Cancel,
when: expected_cancel_block
}
);
assert_ok!(Payment::dispute_refund(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::NeedsReview,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentRefundDisputed {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
}
.into()
);
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)), None);
});
}
#[test]
fn test_request_payment() {
new_test_ext().execute_with(|| {
let payment_amount = 20;
let expected_incentive_amount = 0;
assert_ok!(Payment::request_payment(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR,
CURRENCY_ID,
payment_amount,
));
assert_noop!(
Payment::request_refund(RuntimeOrigin::signed(PAYMENT_CREATOR), PAYMENT_RECIPENT),
crate::Error::<Test>::InvalidAction
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::PaymentRequested,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentRequestCreated {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
}
.into()
);
});
}
#[test]
fn test_requested_payment_cannot_be_released() {
new_test_ext().execute_with(|| {
let payment_amount = 20;
assert_ok!(Payment::request_payment(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR,
CURRENCY_ID,
payment_amount,
));
assert_noop!(
Payment::release(RuntimeOrigin::signed(PAYMENT_CREATOR), PAYMENT_RECIPENT),
Error::InvalidAction
);
});
}
#[test]
fn test_requested_payment_can_be_cancelled_by_requestor() {
new_test_ext().execute_with(|| {
let payment_amount = 20;
assert_ok!(Payment::request_payment(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR,
CURRENCY_ID,
payment_amount,
));
assert_ok!(Payment::cancel(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR
));
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
});
}
#[test]
fn test_accept_and_pay() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = 0;
assert_ok!(Payment::request_payment(
RuntimeOrigin::signed(PAYMENT_RECIPENT),
PAYMENT_CREATOR,
CURRENCY_ID,
payment_amount,
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::PaymentRequested,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
assert_ok!(Payment::accept_and_pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentRequestCompleted {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT,
}
.into()
);
});
}
#[test]
fn test_accept_and_pay_should_fail_for_non_payment_requested() {
new_test_ext().execute_with(|| {
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
20,
None
));
assert_noop!(
Payment::accept_and_pay(RuntimeOrigin::signed(PAYMENT_CREATOR), PAYMENT_RECIPENT,),
Error::InvalidAction
);
});
}
#[test]
fn test_accept_and_pay_should_charge_fee_correctly() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = 0;
let expected_fee_amount = payment_amount / MARKETPLACE_FEE_PERCENTAGE as u128;
assert_ok!(Payment::request_payment(
RuntimeOrigin::signed(PAYMENT_RECIPENT_FEE_CHARGED),
PAYMENT_CREATOR,
CURRENCY_ID,
payment_amount,
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::PaymentRequested,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
assert_ok!(Payment::accept_and_pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED,
));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_fee_amount
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED),
payment_amount
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &FEE_RECIPIENT_ACCOUNT),
expected_fee_amount
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
None
);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentRequestCompleted {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT_FEE_CHARGED,
}
.into()
);
});
}
#[test]
fn test_create_payment_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_fee_amount = 0;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::create_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
PaymentState::Created,
Percent::from_percent(INCENTIVE_PERCENTAGE),
Some(&[1u8; 10]),
)
})));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
assert_noop!(
with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::create_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
PaymentState::Created,
Percent::from_percent(INCENTIVE_PERCENTAGE),
Some(&[1u8; 10]),
)
})),
Error::PaymentAlreadyInProcess
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
});
}
#[test]
fn test_reserve_payment_amount_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
let expected_fee_amount = 0;
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR), 100);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::create_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
PaymentState::Created,
Percent::from_percent(INCENTIVE_PERCENTAGE),
Some(&[1u8; 10]),
)
})));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::reserve_payment_amount(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT).unwrap(),
)
})));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount - expected_incentive_amount
);
assert_eq!(
Tokens::total_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(Tokens::total_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_noop!(
with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::create_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
PaymentState::Created,
Percent::from_percent(INCENTIVE_PERCENTAGE),
Some(&[1u8; 10]),
)
})),
Error::PaymentAlreadyInProcess
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::Created,
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, expected_fee_amount)),
})
);
});
}
#[test]
fn test_settle_payment_works_for_cancel() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::settle_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
Percent::from_percent(0),
)
})));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
});
}
#[test]
fn test_settle_payment_works_for_release() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::settle_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT,
Percent::from_percent(100),
)
})));
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance - payment_amount
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), payment_amount);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
});
}
#[test]
fn test_settle_payment_works_for_70_30() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 10;
let expected_fee_amount = payment_amount / MARKETPLACE_FEE_PERCENTAGE as u128;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED), 0);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::settle_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT_FEE_CHARGED,
Percent::from_percent(70),
)
})));
let expected_amount_for_creator = creator_initial_balance - payment_amount - expected_fee_amount
+ (Percent::from_percent(30) * payment_amount);
let expected_amount_for_recipient = Percent::from_percent(70) * payment_amount;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
expected_amount_for_creator
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED),
expected_amount_for_recipient
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &FEE_RECIPIENT_ACCOUNT),
expected_fee_amount
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
None
);
});
}
#[test]
fn test_settle_payment_works_for_50_50() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 10;
let expected_fee_amount = payment_amount / MARKETPLACE_FEE_PERCENTAGE as u128;
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR), 100);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED), 0);
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT_FEE_CHARGED,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(with_transaction(|| TransactionOutcome::Commit({
<Payment as PaymentHandler<Test>>::settle_payment(
&PAYMENT_CREATOR,
&PAYMENT_RECIPENT_FEE_CHARGED,
Percent::from_percent(50),
)
})));
let expected_amount_for_creator = creator_initial_balance - payment_amount - expected_fee_amount
+ (Percent::from_percent(50) * payment_amount);
let expected_amount_for_recipient = Percent::from_percent(50) * payment_amount;
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
expected_amount_for_creator
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_FEE_CHARGED),
expected_amount_for_recipient
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &FEE_RECIPIENT_ACCOUNT),
expected_fee_amount
);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT_FEE_CHARGED),
None
);
});
}
#[test]
fn test_automatic_refund_works() {
new_test_ext().execute_with(|| {
let creator_initial_balance = 100;
let payment_amount = 20;
let expected_incentive_amount = payment_amount / INCENTIVE_PERCENTAGE as u128;
const CANCEL_PERIOD: u64 = 600;
const CANCEL_BLOCK: u64 = CANCEL_PERIOD + 1;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT),
Some(PaymentDetail {
asset: CURRENCY_ID,
amount: payment_amount,
incentive_amount: expected_incentive_amount,
state: PaymentState::RefundRequested {
cancel_block: CANCEL_BLOCK
},
resolver_account: RESOLVER_ACCOUNT,
fee_detail: Some((FEE_RECIPIENT_ACCOUNT, 0)),
})
);
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(
scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)).unwrap(),
&ScheduledTask {
task: Task::Cancel,
when: CANCEL_BLOCK
}
);
assert_eq!(run_n_blocks(CANCEL_PERIOD - 1), 600);
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(
scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)).unwrap(),
&ScheduledTask {
task: Task::Cancel,
when: CANCEL_BLOCK
}
);
assert_eq!(run_n_blocks(1), 601);
assert!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT).is_some());
assert_eq!(run_n_blocks(1), 602);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)), None);
assert_eq!(
last_event(),
crate::Event::<Test>::PaymentCancelled {
from: PAYMENT_CREATOR,
to: PAYMENT_RECIPENT
}
.into()
);
assert_eq!(
Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR),
creator_initial_balance
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
});
}
#[test]
fn test_automatic_refund_works_for_multiple_payments() {
new_test_ext().execute_with(|| {
const CANCEL_PERIOD: u64 = 600;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
20,
None
));
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR_TWO),
PAYMENT_RECIPENT_TWO,
CURRENCY_ID,
20,
None
));
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
run_n_blocks(1);
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR_TWO),
PAYMENT_RECIPENT_TWO
));
assert_eq!(run_n_blocks(CANCEL_PERIOD - 1), 601);
assert_ok!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT).ok_or(()));
assert_eq!(run_n_blocks(1), 602);
assert_eq!(PaymentStore::<Test>::get(PAYMENT_CREATOR, PAYMENT_RECIPENT), None);
assert_eq!(
PaymentStore::<Test>::get(PAYMENT_CREATOR_TWO, PAYMENT_RECIPENT_TWO),
None
);
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)), None);
assert_eq!(
scheduled_tasks_list.get(&(PAYMENT_CREATOR_TWO, PAYMENT_RECIPENT_TWO)),
None
);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR), 100);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT), 0);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_CREATOR_TWO), 100);
assert_eq!(Tokens::free_balance(CURRENCY_ID, &PAYMENT_RECIPENT_TWO), 0);
});
}
#[test]
fn on_idle_works() {
new_test_ext().execute_with(|| {
assert_eq!(
Payment::on_idle(System::block_number(), Weight::MAX),
<()>::remove_task()
);
let payment_amount = 20;
let expected_cancel_block = CANCEL_BLOCK_BUFFER + 1;
assert_ok!(Payment::pay(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT,
CURRENCY_ID,
payment_amount,
None
));
assert_ok!(Payment::request_refund(
RuntimeOrigin::signed(PAYMENT_CREATOR),
PAYMENT_RECIPENT
));
let scheduled_tasks_list = ScheduledTasks::<Test>::get();
assert_eq!(scheduled_tasks_list.len(), 1);
assert_eq!(
scheduled_tasks_list.get(&(PAYMENT_CREATOR, PAYMENT_RECIPENT)).unwrap(),
&ScheduledTask {
task: Task::Cancel,
when: expected_cancel_block
}
);
assert_eq!(run_n_blocks(CANCEL_BLOCK_BUFFER - 1), 600);
assert_eq!(
Payment::on_idle(System::block_number(), Weight::MAX),
<()>::remove_task()
);
assert_eq!(run_n_blocks(1), 601);
assert_eq!(
Payment::on_idle(System::block_number(), Weight::MAX),
<()>::remove_task() + <()>::cancel()
);
});
}