-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: improved performance and code readability
- Loading branch information
abdulhakim2902
committed
Sep 26, 2022
1 parent
e80527e
commit 50ccaa1
Showing
10 changed files
with
711 additions
and
694 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
use crate::*; | ||
|
||
use frame_support::{ | ||
pallet_prelude::*, | ||
sp_runtime::traits::{AccountIdConversion, Hash}, | ||
PalletId, | ||
}; | ||
use sp_std::vec; | ||
|
||
pub const PALLET_ID: PalletId = PalletId(*b"orders!!"); | ||
|
||
impl<T: Config> Pallet<T> { | ||
pub fn staking_account_id(order_id: HashOf<T>) -> AccountIdOf<T> { | ||
PALLET_ID.into_sub_account(order_id) | ||
} | ||
|
||
pub fn generate_order_id(customer_id: &T::AccountId, service_id: &T::Hash) -> T::Hash { | ||
let mut customer_id_bytes = customer_id.encode(); | ||
let mut service_id_bytes = service_id.encode(); | ||
let account_info = frame_system::Pallet::<T>::account(customer_id); | ||
let mut nonce_bytes = account_info.nonce.encode(); | ||
|
||
customer_id_bytes.append(&mut service_id_bytes); | ||
customer_id_bytes.append(&mut nonce_bytes); | ||
|
||
let seed = &customer_id_bytes; | ||
T::Hashing::hash(seed) | ||
} | ||
|
||
pub fn update_order_status(order_id: &T::Hash, status: OrderStatus) -> Option<OrderOf<T>> { | ||
Orders::<T>::mutate(order_id, |order| match order { | ||
None => None, | ||
Some(order) => { | ||
order.status = status; | ||
order.updated_at = pallet_timestamp::Pallet::<T>::get(); | ||
Some(order.clone()) | ||
}, | ||
}) | ||
} | ||
|
||
pub fn insert_order_to_storage(order: &OrderOf<T>) { | ||
Orders::<T>::insert(order.id, order); | ||
LastOrderByCustomer::<T>::insert(&order.customer_id, order.id); | ||
Self::insert_order_id_into_orders_by_seller(order); | ||
Self::insert_order_id_into_pending_orders_by_seller(order); | ||
Self::insert_order_id_into_orders_by_customer(order); | ||
} | ||
|
||
pub fn insert_order_id_into_orders_by_seller(order: &OrderOf<T>) { | ||
match OrdersBySeller::<T>::get(&order.seller_id) { | ||
None => { | ||
OrdersBySeller::<T>::insert(&order.seller_id, vec![order.id]); | ||
}, | ||
Some(mut orders) => { | ||
orders.push(order.id); | ||
OrdersBySeller::<T>::insert(&order.seller_id, orders); | ||
}, | ||
} | ||
} | ||
|
||
pub fn insert_order_id_into_orders_by_customer(order: &OrderOf<T>) { | ||
match OrdersByCustomer::<T>::get(&order.customer_id) { | ||
None => { | ||
OrdersByCustomer::<T>::insert(&order.customer_id, vec![order.id]); | ||
}, | ||
Some(mut orders) => { | ||
orders.push(order.id); | ||
OrdersByCustomer::<T>::insert(&order.customer_id, orders); | ||
}, | ||
} | ||
} | ||
|
||
pub fn insert_order_id_into_pending_orders_by_seller(order: &OrderOf<T>) { | ||
match PendingOrdersBySeller::<T>::get(&order.seller_id) { | ||
None => { | ||
PendingOrdersBySeller::<T>::insert(&order.seller_id, vec![order.id]); | ||
}, | ||
Some(mut orders) => { | ||
orders.push(order.id); | ||
PendingOrdersBySeller::<T>::insert(&order.seller_id, orders); | ||
}, | ||
} | ||
} | ||
|
||
pub fn remove_order_id_from_pending_orders_by_seller( | ||
seller_id: &T::AccountId, | ||
order_id: &T::Hash, | ||
) { | ||
let mut orders = PendingOrdersBySeller::<T>::get(seller_id).unwrap_or_default(); | ||
orders.retain(|o_id| o_id != order_id); | ||
PendingOrdersBySeller::<T>::insert(seller_id, orders); | ||
} | ||
|
||
pub fn remove_order_id_from_orders_by_seller(seller_id: &T::AccountId, order_id: &T::Hash) { | ||
let mut orders = OrdersBySeller::<T>::get(seller_id).unwrap_or_default(); | ||
orders.retain(|o_id| o_id != order_id); | ||
OrdersBySeller::<T>::insert(seller_id, orders); | ||
} | ||
|
||
pub fn remove_order_id_from_orders_by_customer(customer_id: &T::AccountId, order_id: &T::Hash) { | ||
let mut orders = OrdersByCustomer::<T>::get(customer_id).unwrap_or_default(); | ||
orders.retain(|o_id| o_id != order_id); | ||
OrdersByCustomer::<T>::insert(customer_id, orders); | ||
} | ||
|
||
pub fn order_can_be_refunded(order: OrderOf<T>) -> bool { | ||
let dna_sample = | ||
T::GeneticTesting::dna_sample_by_tracking_id(&order.dna_sample_tracking_id).unwrap(); | ||
if !dna_sample.is_rejected() { | ||
return false | ||
} | ||
true | ||
} | ||
|
||
fn is_pending_order_ids_by_seller_exist(account_id: &T::AccountId) -> bool { | ||
match PendingOrdersBySeller::<T>::get(account_id) { | ||
Some(_arr) => !_arr.is_empty(), | ||
None => false, | ||
} | ||
} | ||
} | ||
|
||
impl<T: Config> OrderEventEmitter<T> for Pallet<T> { | ||
fn emit_event_order_failed(order_id: &HashOf<T>) { | ||
match Self::order_by_id(order_id) { | ||
None => Self::deposit_event(Event::OrderNotFound), | ||
Some(order) => Self::deposit_event(Event::OrderFailed(order)), | ||
} | ||
} | ||
} | ||
|
||
impl<T: Config> OrderStatusUpdater<T> for Pallet<T> { | ||
fn update_status_failed(order_id: &HashOf<T>) { | ||
match Self::order_by_id(order_id) { | ||
None => Self::deposit_event(Event::OrderNotFound), | ||
Some(order) => { | ||
Self::update_order_status(&order.id, OrderStatus::Failed); | ||
}, | ||
} | ||
} | ||
|
||
fn remove_order_id_from_pending_orders_by_seller( | ||
seller_id: &AccountIdOf<T>, | ||
order_id: &HashOf<T>, | ||
) { | ||
Self::remove_order_id_from_pending_orders_by_seller(seller_id, order_id); | ||
} | ||
|
||
fn is_pending_order_by_seller_exist(seller_id: &AccountIdOf<T>) -> bool { | ||
Self::is_pending_order_ids_by_seller_exist(seller_id) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
use crate::*; | ||
|
||
impl<T: Config> OrderInterface<T> for Pallet<T> { | ||
type Order = OrderOf<T>; | ||
type Error = Error<T>; | ||
|
||
fn create_order( | ||
customer_id: &T::AccountId, | ||
service_id: &T::Hash, | ||
price_index: u32, | ||
customer_box_public_key: &T::Hash, | ||
order_flow: ServiceFlow, | ||
) -> Result<Self::Order, Self::Error> { | ||
let service = | ||
T::Services::service_by_id(service_id).ok_or(Error::<T>::ServiceDoesNotExist)?; | ||
|
||
let order_id = Self::generate_order_id(customer_id, service_id); | ||
let seller_id = service.get_owner_id(); | ||
let prices_by_currency = service.get_prices_by_currency(); | ||
|
||
if prices_by_currency.is_empty() || | ||
prices_by_currency.len() - 1 < price_index.try_into().unwrap() | ||
{ | ||
return Err(Error::<T>::PriceIndexNotFound) | ||
} | ||
|
||
let price_by_currency = &prices_by_currency[price_index as usize]; | ||
|
||
let currency = &price_by_currency.currency; | ||
let prices = &price_by_currency.price_components; | ||
let additional_prices = &price_by_currency.additional_prices; | ||
|
||
let now = pallet_timestamp::Pallet::<T>::get(); | ||
|
||
// Initialize DnaSample | ||
let dna_sample = T::GeneticTesting::register_dna_sample(seller_id, customer_id, &order_id) | ||
.map_err(|_| Error::<T>::DnaSampleInitalizationError)?; | ||
|
||
let order = Order::new( | ||
order_id, | ||
*service_id, | ||
customer_id.clone(), | ||
*customer_box_public_key, | ||
seller_id.clone(), | ||
dna_sample.get_tracking_id().clone(), | ||
currency.clone(), | ||
order_flow, | ||
prices.clone(), | ||
additional_prices.clone(), | ||
now, | ||
now, | ||
); | ||
|
||
Self::insert_order_to_storage(&order); | ||
|
||
Ok(order) | ||
} | ||
|
||
fn cancel_order( | ||
customer_id: &T::AccountId, | ||
order_id: &T::Hash, | ||
) -> Result<Self::Order, Self::Error> { | ||
let order = Orders::<T>::get(order_id).ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
if order.get_customer_id() != customer_id { | ||
return Err(Error::<T>::UnauthorizedOrderCancellation) | ||
} | ||
|
||
let dna_sample_result = | ||
T::GeneticTesting::dna_sample_by_tracking_id(&order.dna_sample_tracking_id); | ||
|
||
if let Some(dna_sample) = dna_sample_result { | ||
if !dna_sample.is_registered() { | ||
return Err(Error::<T>::OngoingOrderCannotBeCancelled) | ||
} | ||
} | ||
|
||
// Delete dna sample associated with the order | ||
let _ = T::GeneticTesting::delete_dna_sample(&order.dna_sample_tracking_id); | ||
|
||
let order = Self::update_order_status(order_id, OrderStatus::Cancelled) | ||
.ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
Ok(order) | ||
} | ||
|
||
fn set_order_paid( | ||
escrow_account_id: &T::AccountId, | ||
order_id: &T::Hash, | ||
) -> Result<Self::Order, Self::Error> { | ||
let _ = EscrowKey::<T>::get() | ||
.filter(|account_id| account_id == escrow_account_id) | ||
.ok_or(Error::<T>::Unauthorized)?; | ||
|
||
let order = Self::update_order_status(order_id, OrderStatus::Paid) | ||
.ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
Ok(order) | ||
} | ||
|
||
fn fulfill_order( | ||
seller_id: &T::AccountId, | ||
order_id: &T::Hash, | ||
) -> Result<Self::Order, Self::Error> { | ||
let order = Orders::<T>::get(order_id).ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
// Only the seller can fulfill the order | ||
if order.get_seller_id() != seller_id { | ||
return Err(Error::<T>::UnauthorizedOrderFulfillment) | ||
} | ||
|
||
let dna_sample_result = | ||
T::GeneticTesting::dna_sample_by_tracking_id(&order.dna_sample_tracking_id); | ||
|
||
if let Some(dna_sample) = dna_sample_result { | ||
if !dna_sample.process_success() { | ||
return Err(Error::<T>::DnaSampleNotSuccessfullyProcessed) | ||
} | ||
} | ||
|
||
let order = Self::update_order_status(order_id, OrderStatus::Fulfilled) | ||
.ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
Ok(order) | ||
} | ||
|
||
fn set_order_refunded( | ||
escrow_account_id: &T::AccountId, | ||
order_id: &T::Hash, | ||
) -> Result<Self::Order, Self::Error> { | ||
let _ = EscrowKey::<T>::get() | ||
.filter(|account_id| account_id == escrow_account_id) | ||
.ok_or(Error::<T>::Unauthorized)?; | ||
|
||
let order = Orders::<T>::get(order_id).ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
if !Self::order_can_be_refunded(order) { | ||
return Err(Error::<T>::OrderNotYetExpired) | ||
} | ||
|
||
let order = Self::update_order_status(order_id, OrderStatus::Refunded) | ||
.ok_or(Error::<T>::OrderNotFound)?; | ||
|
||
Ok(order) | ||
} | ||
|
||
fn update_escrow_key( | ||
account_id: &T::AccountId, | ||
escrow_key: &T::AccountId, | ||
) -> Result<(), Self::Error> { | ||
let _ = EscrowKey::<T>::get() | ||
.filter(|e| e == account_id) | ||
.ok_or(Error::<T>::Unauthorized)?; | ||
|
||
EscrowKey::<T>::put(escrow_key); | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.