Skip to content

Commit b78bb50

Browse files
committed
Merge branch 'main' of github.com-keyanhov:gridsingularity/gsy-decentralized-exchange into feature/DD-343
2 parents f5b34f5 + ce0e30a commit b78bb50

39 files changed

+7544
-348
lines changed

gsy-node/modules/orderbook-worker/src/configuration.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ use core::option_env;
33
use codec::alloc::string::ToString;
44

55
#[derive(Debug)]
6-
pub struct OrderBookServiceURL {
7-
pub url: String,
6+
pub struct OrderBookServiceURLs {
7+
pub orders_url: String,
8+
pub trades_url: String
89
}
910

10-
impl Default for OrderBookServiceURL{
11+
impl Default for OrderBookServiceURLs{
1112
fn default() -> Self {
1213
// Set the environment variable "URL" for OrderBook_Service
1314
let base_url = option_env!("ORDERBOOK_SERVICE_URL")
1415
.unwrap_or("http://localhost:8080");
15-
16-
OrderBookServiceURL { url: base_url.to_string() }
16+
17+
OrderBookServiceURLs{
18+
orders_url: format!("{}/orders", orderbook_url),
19+
trades_url: format!("{}/trades", orderbook_url),
20+
}
1721
}
1822
}
1923

gsy-node/modules/orderbook-worker/src/lib.rs

Lines changed: 151 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ use sp_core::crypto::KeyTypeId;
77
pub use crate::weights::WeightInfo;
88
pub use pallet::*;
99

10+
pub use scale_info::prelude::vec::Vec;
1011
pub use sp_core::offchain::Timestamp;
1112
use sp_runtime::offchain::{http, Duration};
1213
pub use sp_std::sync::Arc;
13-
pub use scale_info::prelude::vec::Vec;
1414

1515
pub mod configuration;
16-
use configuration::OrderBookServiceURL;
16+
use configuration::OrderBookServiceURLs;
1717

1818
#[cfg(test)]
1919
mod mock;
@@ -29,13 +29,13 @@ pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"ocw!");
2929

3030
pub mod crypto {
3131
use super::KEY_TYPE;
32+
use scale_info::prelude::string::String;
3233
use sp_core::sr25519::Signature as Sr25519Signature;
3334
use sp_runtime::{
3435
app_crypto::{app_crypto, sr25519},
3536
traits::Verify,
3637
MultiSignature, MultiSigner,
3738
};
38-
use scale_info::prelude::string::String;
3939

4040
app_crypto!(sr25519, KEY_TYPE);
4141

@@ -61,8 +61,7 @@ pub mod crypto {
6161
pub mod pallet {
6262
use super::*;
6363
use frame_support::{
64-
pallet_prelude::*, require_transactional, sp_runtime::traits::Hash,
65-
transactional,
64+
pallet_prelude::*, require_transactional, sp_runtime::traits::Hash, transactional,
6665
};
6766
use frame_system::{
6867
offchain::{
@@ -72,9 +71,9 @@ pub mod pallet {
7271
pallet_prelude::*,
7372
};
7473
use gsy_primitives::v0::{
75-
Bid, InputOrder, Offer, Order, OrderReference, OrderSchema,
76-
OrderStatus,
74+
Bid, InputOrder, Offer, Order, OrderReference, OrderSchema, OrderStatus,
7775
};
76+
use gsy_primitives::Trade;
7877
use scale_info::prelude::vec;
7978
use scale_info::TypeInfo;
8079
use sp_runtime::offchain::http::Request;
@@ -101,24 +100,33 @@ pub mod pallet {
101100
type UnsignedPriority: Get<TransactionPriority>;
102101

103102
type WeightInfo: WeightInfo;
104-
105103
}
106104

107105
#[pallet::pallet]
108106
// #[pallet::generate_store(pub (super) trait Store)]
109107
pub struct Pallet<T>(_);
110108

111109
#[pallet::storage]
112-
#[pallet::getter(fn orders_book)]
110+
#[pallet::getter(fn orderbook)]
113111
/// Temporary orders book for Orderbook workers.
114-
pub type Orderbook<T: Config> = StorageMap<
112+
pub type OrdersForWorker<T: Config> = StorageMap<
115113
_,
116114
Twox64Concat,
117115
OrderReference<T::AccountId, T::Hash>,
118116
Order<T::AccountId>,
119117
OptionQuery,
120118
>;
121119

120+
#[pallet::storage]
121+
#[pallet::getter(fn trades_for_worker)]
122+
/// Temporary trades for Orderbook workers.
123+
pub type TradesForWorker<T: Config> = StorageMap<
124+
_,
125+
Twox64Concat,
126+
T::Hash,
127+
Trade<T::AccountId, T::Hash>,
128+
>;
129+
122130
#[pallet::storage]
123131
#[pallet::getter(fn user_nonce)]
124132
pub type UserNonce<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, u32>;
@@ -133,6 +141,9 @@ pub mod pallet {
133141
OrderRemoved(T::AccountId, T::Hash),
134142
/// New Order added to the orders book \[sender, hash\].
135143
NewOrderInserted(Order<T::AccountId>, T::Hash),
144+
NewTradeInserted(Trade<T::AccountId, T::Hash>, T::Hash),
145+
/// Order has been deleted from the book.
146+
TradeRemoved(T::Hash),
136147
}
137148

138149
#[pallet::error]
@@ -143,6 +154,7 @@ pub mod pallet {
143154
NoLocalAcctForSigning,
144155
NonceCheckOverflow,
145156
OrderIsNotRegistered,
157+
TradeIsNotRegistered,
146158
NotARootUser,
147159
InsufficientCollateral,
148160
InvalidNonce,
@@ -205,7 +217,10 @@ pub mod pallet {
205217
);
206218
let hashed_orders = Self::create_hash_vec_from_order_list(orders.clone());
207219
let _ = <orderbook_registry::Pallet<T>>::insert_orders_by_proxy(
208-
origin, delegator.clone(), hashed_orders);
220+
origin,
221+
delegator.clone(),
222+
hashed_orders,
223+
);
209224
for order in orders {
210225
Self::add_order(delegator.clone(), Self::input_order_to_order(order))?;
211226
}
@@ -220,10 +235,7 @@ pub mod pallet {
220235
#[transactional]
221236
#[pallet::weight(< T as Config >::WeightInfo::remove_orders())]
222237
#[pallet::call_index(2)]
223-
pub fn remove_orders(
224-
origin: OriginFor<T>,
225-
orders_hash: Vec<T::Hash>,
226-
) -> DispatchResult {
238+
pub fn remove_orders(origin: OriginFor<T>, orders_hash: Vec<T::Hash>) -> DispatchResult {
227239
let sender = ensure_signed(origin.clone())?;
228240
log::info!("remove orders: {:?} for the user: {:?}", orders_hash, sender);
229241
let _ = <orderbook_registry::Pallet<T>>::delete_orders(origin, orders_hash);
@@ -252,10 +264,7 @@ pub mod pallet {
252264
);
253265
let mut hash_vector = Vec::<T::Hash>::new();
254266
hash_vector.push(payload.hash);
255-
<orderbook_registry::Pallet<T>>::delete_orders(
256-
origin.clone(),
257-
hash_vector,
258-
)?;
267+
<orderbook_registry::Pallet<T>>::delete_orders(origin.clone(), hash_vector)?;
259268
Self::delete_order(payload)?;
260269
}
261270
Ok(())
@@ -309,7 +318,10 @@ pub mod pallet {
309318
);
310319

311320
let _ = <orderbook_registry::Pallet<T>>::delete_orders_by_proxy(
312-
origin, delegator.clone(), orders_hash.clone());
321+
origin,
322+
delegator.clone(),
323+
orders_hash.clone(),
324+
);
313325
Ok(())
314326
}
315327
}
@@ -402,7 +414,10 @@ pub mod pallet {
402414

403415
let mut orders = Vec::<Order<T::AccountId>>::new();
404416

405-
for (order_ref, order) in <Orderbook<T>>::iter() {
417+
let mut trades = Vec::<Trade<T::AccountId, T::Hash>>::new();
418+
let mut trade_hashes = Vec::<T::Hash>::new();
419+
420+
for (order_ref, order) in <OrdersForWorker<T>>::iter() {
406421
match &order {
407422
_order_in_book => {
408423
log::info!(
@@ -438,16 +453,84 @@ pub mod pallet {
438453
.expect("Error while removing processed orders");
439454
}
440455
}
456+
457+
// TODO: Trades transmission process starts here
458+
459+
for (trade_hash, trade) in <TradesForWorker<T>>::iter() {
460+
match &trade {
461+
_trade_in_book => {
462+
log::info!(
463+
"Offchain process: reference: {:?}, order: {:?}",
464+
&trade_hash,
465+
&trade
466+
);
467+
trades.push(trade);
468+
trade_hashes.push(trade_hash);
469+
},
470+
}
471+
}
472+
473+
if !trades.is_empty() {
474+
// let trade_schema: Vec<Trade<T::AccountId, T::Hash>> = trades
475+
// .clone()
476+
// .into_iter()
477+
// .map(|trade| Trade {
478+
// seller: trade.seller,
479+
// buyer: trade.buyer,
480+
// market_id: trade.market_id,
481+
// trade_uuid: trade.trade_uuid,
482+
// creation_time: trade.creation_time,
483+
// time_slot: trade.time_slot,
484+
// offer: trade.offer,
485+
// offer_hash: trade.offer_hash,
486+
// bid: trade.bid,
487+
// bid_hash: trade.bid_hash,
488+
// residual_offer
489+
//
490+
// })
491+
// .collect();
492+
let bytes = trades.encode();
493+
let bytes_to_json: Vec<u8> = serde_json::to_vec(&bytes).unwrap();
494+
let post_trades_status_code =
495+
Self::send_trade_to_orderbook_service(&bytes_to_json).unwrap();
496+
497+
if post_trades_status_code != 200 {
498+
log::warn!(
499+
"Offchain worker failed to send trades to the orderbook service, HTTP \
500+
response code {}", post_trades_status_code)
501+
}
502+
else {
503+
for trade_hash in trade_hashes {
504+
Self::delete_trade(trade_hash).unwrap();
505+
}
506+
}
507+
}
508+
}
509+
510+
pub fn send_trade_to_orderbook_service(request_body: &[u8]) -> Result<u16, http::Error> {
511+
// deadline sets the offchain worker execution time minimal as possible. So we hard
512+
// code the duration to 2s to complete the external call to the database to post the
513+
// orders.
514+
let orderbook_service_urls = OrderBookServiceURLs::default();
515+
let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(2_000));
516+
let request = Request::post(&orderbook_service_urls.trades_url, vec![&request_body]);
517+
let pending = request
518+
.deadline(deadline)
519+
.add_header("Content-Type", "application/json")
520+
.send()
521+
.map_err(|_| http::Error::DeadlineReached)?;
522+
let response =
523+
pending.try_wait(deadline).map_err(|_| http::Error::DeadlineReached)??;
524+
Ok(response.code)
441525
}
442526

443527
pub fn send_order_to_orderbook_service(request_body: &[u8]) -> Result<u16, http::Error> {
444528
// deadline sets the offchain worker execution time minimal as possible. So we hard
445529
// code the duration to 2s to complete the external call to the database to post the
446530
// orders.
447-
let orderbook_service_url = OrderBookServiceURL::default();
448-
let full_url = orderbook_service_url.with_endpoint("orders");
531+
let orderbook_service_url = OrderBookServiceURLs::default();
449532
let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(2_000));
450-
let request = Request::post(&full_url, vec![&request_body]);
533+
let request = Request::post(&orderbook_service_url.orders_url, vec![&request_body]);
451534
let pending = request
452535
.deadline(deadline)
453536
.add_header("Content-Type", "application/json")
@@ -536,10 +619,7 @@ pub mod pallet {
536619
/// `sender`: The sender of the order.
537620
/// `order`: The order to be inserted.
538621
#[require_transactional]
539-
pub fn add_order(
540-
sender: T::AccountId,
541-
order: Order<T::AccountId>,
542-
) -> DispatchResult {
622+
pub fn add_order(sender: T::AccountId, order: Order<T::AccountId>) -> DispatchResult {
543623
ensure!(
544624
<gsy_collateral::Pallet<T>>::verify_collateral_amount(
545625
Self::get_order_amount(order.clone()),
@@ -550,11 +630,25 @@ pub mod pallet {
550630
let order_hash = T::Hashing::hash_of(&order);
551631
let order_reference =
552632
OrderReference { user_id: sender.clone(), hash: order_hash.clone() };
553-
<Orderbook<T>>::insert(order_reference, order.clone());
633+
<OrdersForWorker<T>>::insert(order_reference, order.clone());
554634
Self::deposit_event(Event::NewOrderInserted(order, order_hash));
555635
Ok(())
556636
}
557637

638+
/// Insert a new trade object into the Trades storage for offchain worker to relay them to
639+
/// orderbook service.
640+
///
641+
/// Parameters
642+
/// `sender`: The sender of the trade.
643+
/// `trade`: The order to be inserted.
644+
#[require_transactional]
645+
pub fn add_trade(_sender: T::AccountId, trade: Trade<T::AccountId, T::Hash>) -> DispatchResult {
646+
let trade_hash = T::Hashing::hash_of(&trade);
647+
<TradesForWorker<T>>::insert(trade_hash, trade.clone());
648+
Self::deposit_event(Event::NewTradeInserted(trade, trade_hash));
649+
Ok(())
650+
}
651+
558652
/// Get nonce for the order.
559653
///
560654
/// Parameters
@@ -563,31 +657,51 @@ pub mod pallet {
563657
/// `u32`: The nonce for the order.
564658
pub fn get_and_increment_user_nonce(sender: T::AccountId) -> u32 {
565659
let user_nonce = <UserNonce<T>>::get(sender.clone()).unwrap_or(0u32);
566-
let nonce = user_nonce.checked_add(1u32)
567-
.ok_or(<Error<T>>::NonceCheckOverflow).unwrap();
660+
let nonce = user_nonce.checked_add(1u32).ok_or(<Error<T>>::NonceCheckOverflow).unwrap();
568661
<UserNonce<T>>::insert(sender.clone(), nonce);
569662
user_nonce
570663
}
571664

572-
/// Remove a order from the orders book.
665+
/// Remove an order from the orders book.
573666
///
574667
/// Parameters
575668
/// `order_reference`: The order reference.
576669
pub fn delete_order(
577670
order_reference: OrderReference<T::AccountId, T::Hash>,
578671
) -> DispatchResult {
579672
ensure!(Self::is_order_registered(&order_reference), <Error<T>>::OrderIsNotRegistered);
580-
<Orderbook<T>>::remove(order_reference.clone());
673+
<OrdersForWorker<T>>::remove(order_reference.clone());
581674
Self::deposit_event(Event::OrderRemoved(order_reference.user_id, order_reference.hash));
582675
Ok(())
583676
}
584677

678+
/// Remove a trade from the offchain worker storage.
679+
///
680+
/// Parameters
681+
/// `trade_hash`: The hash of the trade object.
682+
pub fn delete_trade(
683+
trade_hash: T::Hash,
684+
) -> DispatchResult {
685+
ensure!(Self::is_trade_registered(&trade_hash), <Error<T>>::TradeIsNotRegistered);
686+
<TradesForWorker<T>>::remove(trade_hash);
687+
Self::deposit_event(Event::TradeRemoved(trade_hash));
688+
Ok(())
689+
}
690+
691+
/// Helper function to check if a given order has already been registered.
692+
///
693+
/// Parameters
694+
/// `trade_hash`: The hash of the trade.
695+
pub fn is_trade_registered(trade_hash: &T::Hash) -> bool {
696+
<TradesForWorker<T>>::contains_key(trade_hash)
697+
}
698+
585699
/// Helper function to check if a given order has already been registered.
586700
///
587701
/// Parameters
588702
/// `order_ref`: The order reference.
589703
pub fn is_order_registered(order_ref: &OrderReference<T::AccountId, T::Hash>) -> bool {
590-
<Orderbook<T>>::contains_key(order_ref)
704+
<OrdersForWorker<T>>::contains_key(order_ref)
591705
}
592706

593707
/// Helper function to get the user_id of the order
@@ -622,14 +736,15 @@ pub mod pallet {
622736
}
623737
}
624738

625-
pub fn create_hash_vec_from_order_list(orders: Vec<InputOrder<T::AccountId>>) -> Vec<T::Hash> {
739+
pub fn create_hash_vec_from_order_list(
740+
orders: Vec<InputOrder<T::AccountId>>,
741+
) -> Vec<T::Hash> {
626742
return orders
627743
.clone()
628744
.into_iter()
629745
.map(|order| Self::input_order_to_order(order))
630746
.map(|order| T::Hashing::hash_of(&order))
631747
.collect();
632748
}
633-
634749
}
635750
}

0 commit comments

Comments
 (0)