use super::{Operation, Vault};
use crate::client::COST_OF_PUT;
use safe_nd::{Coins, Error as SndError, LoginPacketRequest, PublicKey, Response, Transaction};
use std::str::FromStr;
use unwrap::unwrap;
impl Vault {
pub(crate) fn process_login_packet_req(
&mut self,
request: &LoginPacketRequest,
requester_pk: PublicKey,
owner_pk: PublicKey,
) -> Response {
match request {
LoginPacketRequest::CreateFor {
new_owner,
amount,
transaction_id,
new_login_packet,
} => {
let source = owner_pk.into();
let new_balance_dest = (*new_owner).into();
let result = if let Err(e) = {
let mut req_perms = vec![Operation::Mutation];
if *amount == unwrap!(Coins::from_str("0")) {
req_perms.push(Operation::TransferCoins);
}
self.authorise_operations(req_perms.as_slice(), source, requester_pk)
} {
Err(e)
} else {
self.get_balance(&source)
.and_then(|source_balance| {
let debit_amt = amount
.checked_add(COST_OF_PUT)
.ok_or(SndError::ExcessiveValue)?;
if !self.has_sufficient_balance(source_balance, debit_amt) {
return Err(SndError::InsufficientBalance);
}
self.create_balance(new_balance_dest, *new_owner)
})
.and_then(|_| {
self.commit_mutation(&source);
self.transfer_coins(source, new_balance_dest, *amount, *transaction_id)
})
.and_then(|_| {
if self
.get_login_packet(new_login_packet.destination())
.is_some()
{
Err(SndError::LoginPacketExists)
} else {
Ok(())
}
})
.map(|_| {
self.insert_login_packet(new_login_packet.clone());
Transaction {
id: *transaction_id,
amount: *amount,
}
})
};
Response::Transaction(result)
}
LoginPacketRequest::Create(account_data) => {
let source = owner_pk.into();
if let Err(e) =
self.authorise_operations(&[Operation::Mutation], source, requester_pk)
{
Response::Mutation(Err(e))
} else if self.get_login_packet(account_data.destination()).is_some() {
Response::Mutation(Err(SndError::LoginPacketExists))
} else {
let result = self
.get_balance(&source)
.and_then(|source_balance| {
if !self.has_sufficient_balance(source_balance, COST_OF_PUT) {
return Err(SndError::InsufficientBalance);
}
self.commit_mutation(&source);
Ok(())
})
.map(|_| self.insert_login_packet(account_data.clone()));
Response::Mutation(result)
}
}
LoginPacketRequest::Get(location) => {
let result = match self.get_login_packet(&location) {
None => Err(SndError::NoSuchLoginPacket),
Some(login_packet) => {
if *login_packet.authorised_getter() == requester_pk {
Ok((
login_packet.data().to_vec(),
login_packet.signature().clone(),
))
} else {
Err(SndError::AccessDenied)
}
}
};
Response::GetLoginPacket(result)
}
LoginPacketRequest::Update(new_packet) => {
let result = {
match self.get_login_packet(new_packet.destination()) {
Some(old_packet) => {
if *old_packet.authorised_getter() == requester_pk {
self.insert_login_packet(new_packet.clone());
Ok(())
} else {
Err(SndError::AccessDenied)
}
}
None => Err(SndError::NoSuchLoginPacket),
}
};
Response::Mutation(result)
}
}
}
}