Skip to content

Commit

Permalink
Save market price when update balance and transfer (#344)
Browse files Browse the repository at this point in the history
* Save market price when update balance and transfer.

* Update
  • Loading branch information
silathdiir authored Oct 18, 2021
1 parent 138f8a0 commit ae56c74
Showing 1 changed file with 36 additions and 17 deletions.
53 changes: 36 additions & 17 deletions src/matchengine/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ use std::collections::HashMap;
use std::convert::TryFrom;
use std::str::FromStr;

type MarketName = String;
type BaseAsset = String;
type QuoteAsset = String;

pub trait OperationLogConsumer {
fn is_block(&self) -> bool;
fn append_operation_log(&mut self, item: models::OperationLog) -> anyhow::Result<(), models::OperationLog>;
Expand Down Expand Up @@ -92,7 +96,8 @@ pub struct Controller {
pub eth_guard: EthLogGuard,
// pub asset_manager: AssetManager,
pub update_controller: BalanceUpdateController,
pub markets: HashMap<String, market::Market>,
pub markets: HashMap<MarketName, market::Market>,
pub asset_market_names: HashMap<(BaseAsset, QuoteAsset), MarketName>,
// TODO: is it worth to use generics rather than dynamic pointer?
pub log_handler: Box<dyn OperationLogConsumer + Send + Sync>,
pub persistor: Box<dyn PersistExector>,
Expand Down Expand Up @@ -121,9 +126,11 @@ pub fn create_controller(cfgs: (config::Settings, MarketConfigs)) -> Controller
// let asset_manager = AssetManager::new(&settings.assets).unwrap();
let sequencer = Sequencer::default();
let mut markets = HashMap::new();
let mut asset_market_names = HashMap::new();
for entry in &settings.markets {
let market = market::Market::new(entry, &settings, &balance_manager).unwrap();
markets.insert(entry.name.clone(), market);
asset_market_names.insert((entry.base.clone(), entry.quote.clone()), entry.name.clone());
}

let persistor = create_persistor(&settings);
Expand All @@ -143,6 +150,7 @@ pub fn create_controller(cfgs: (config::Settings, MarketConfigs)) -> Controller
eth_guard: EthLogGuard::new(0),
update_controller,
markets,
asset_market_names,
log_handler: Box::<OperationLogSender>::new(log_handler),
persistor,
dummy_persistor: DummyPersistor::new_box(),
Expand Down Expand Up @@ -412,10 +420,11 @@ impl Controller {
return Ok(BalanceUpdateResponse::default());
}

if !self.balance_manager.asset_manager.asset_exist(&req.asset) {
let asset = &req.asset;
if !self.balance_manager.asset_manager.asset_exist(asset) {
return Err(Status::invalid_argument("invalid asset"));
}
let prec = self.balance_manager.asset_manager.asset_prec_show(&req.asset);
let prec = self.balance_manager.asset_manager.asset_prec_show(asset);
let change_result = Decimal::from_str(req.delta.as_str()).map_err(|_| Status::invalid_argument("invalid amount"))?;
let change = change_result.round_dp(prec);
let detail_json: serde_json::Value = if req.detail.is_empty() {
Expand All @@ -430,6 +439,11 @@ impl Controller {
} else {
BusinessType::Withdraw
};
// Get market price of requested base asset and quote asset of USDT.
let market_price = match self.asset_market_names.get(&(asset.to_owned(), "USDT".to_owned())) {
Some(market_name) => self.markets.get(market_name).unwrap().price,
None => Decimal::zero(),
};
self.update_controller
.update_user_balance(
&mut self.balance_manager,
Expand All @@ -438,10 +452,10 @@ impl Controller {
balance_type: BalanceType::AVAILABLE,
business_type,
user_id: req.user_id,
asset: req.asset.to_string(),
asset: asset.to_owned(),
business: req.business.clone(),
business_id: req.business_id,
market_price: Decimal::zero(),
market_price,
change,
detail: detail_json,
signature: req.signature.clone().map_or_else(Vec::new, |sig| sig.as_bytes().to_vec()),
Expand Down Expand Up @@ -604,7 +618,8 @@ impl Controller {
for entry in new_markets.into_iter() {
let handle_ret = if self.markets.get(&entry.name).is_none() {
market::Market::new(&entry, &self.settings, &self.balance_manager).map(|mk| {
self.markets.insert(entry.name, mk);
self.markets.insert(entry.name.clone(), mk);
self.asset_market_names.insert((entry.base, entry.quote), entry.name);
})
} else {
Err(anyhow!("market {} is duplicated", entry.name))
Expand All @@ -623,8 +638,8 @@ impl Controller {
return Err(Status::unavailable(""));
}

let asset_id = &req.asset;
if !self.balance_manager.asset_manager.asset_exist(asset_id) {
let asset = &req.asset;
if !self.balance_manager.asset_manager.asset_exist(asset) {
return Err(Status::invalid_argument("invalid asset"));
}

Expand All @@ -635,20 +650,20 @@ impl Controller {
}

let balance_manager = &self.balance_manager;
let balance_from = balance_manager.get(from_user_id, BalanceType::AVAILABLE, asset_id);
let balance_from = balance_manager.get(from_user_id, BalanceType::AVAILABLE, asset);

let zero = Decimal::from(0);
let delta = Decimal::from_str(&req.delta).unwrap_or(zero);

if delta <= zero || delta > balance_from {
return Ok(TransferResponse {
success: false,
asset: asset_id.to_owned(),
asset: asset.to_owned(),
balance_from: balance_from.to_string(),
});
}

let prec = self.balance_manager.asset_manager.asset_prec_show(asset_id);
let prec = self.balance_manager.asset_manager.asset_prec_show(asset);
let change = delta.round_dp(prec);

let business = "transfer";
Expand All @@ -660,7 +675,11 @@ impl Controller {
serde_json::from_str(req.memo.as_str()).map_err(|_| Status::invalid_argument("invalid memo"))?
};

//let persistor = self.get_persistor(real);
// Get market price of requested base asset and quote asset of USDT.
let market_price = self
.asset_market_names
.get(&(asset.to_owned(), "USDT".to_owned()))
.map_or(Decimal::zero(), |market_name| self.markets.get(market_name).unwrap().price);
let persistor = if real { &mut self.persistor } else { &mut self.dummy_persistor };
self.update_controller
.update_user_balance(
Expand All @@ -670,10 +689,10 @@ impl Controller {
balance_type: BalanceType::AVAILABLE,
business_type: BusinessType::Transfer,
user_id: from_user_id,
asset: asset_id.to_owned(),
asset: asset.to_owned(),
business: business.to_owned(),
business_id,
market_price: Decimal::zero(),
market_price,
change: -change,
detail: detail_json.clone(),
signature: vec![],
Expand All @@ -690,7 +709,7 @@ impl Controller {
balance_type: BalanceType::AVAILABLE,
business_type: BusinessType::Transfer,
user_id: to_user_id,
asset: asset_id.to_owned(),
asset: asset.to_owned(),
business: business.to_owned(),
business_id,
market_price: Decimal::zero(),
Expand All @@ -706,7 +725,7 @@ impl Controller {
time: timestamp.into(),
user_from: from_user_id as i32, // TODO: will this overflow?
user_to: to_user_id as i32, // TODO: will this overflow?
asset: asset_id.to_string(),
asset: asset.to_owned(),
amount: change,
signature: req.signature.as_bytes().to_vec(),
});
Expand All @@ -716,7 +735,7 @@ impl Controller {

Ok(TransferResponse {
success: true,
asset: asset_id.to_owned(),
asset: asset.to_owned(),
balance_from: (balance_from - change).to_string(),
})
}
Expand Down

0 comments on commit ae56c74

Please sign in to comment.