use super::{Operation, Vault};
use crate::client::COST_OF_PUT;
use safe_nd::{Coins, CoinsRequest, Error as SndError, PublicKey, Response, Transaction};
use std::str::FromStr;
use unwrap::unwrap;
use xor_name::XorName;
impl Vault {
pub(crate) fn process_coins_req(
&mut self,
request: &CoinsRequest,
requester_pk: PublicKey,
owner_pk: PublicKey,
) -> Response {
match request {
CoinsRequest::Transfer {
destination,
amount,
transaction_id,
} => {
let source: XorName = owner_pk.into();
let result = if amount.as_nano() == 0 {
Err(SndError::InvalidOperation)
} else {
self.authorise_operations(&[Operation::TransferCoins], source, requester_pk)
.and_then(|()| {
self.transfer_coins(source, *destination, *amount, *transaction_id)
})
};
Response::Transaction(result)
}
CoinsRequest::CreateBalance {
amount,
new_balance_owner,
transaction_id,
} => {
let source = owner_pk.into();
let destination = (*new_balance_owner).into();
let result = if source == destination {
self.mock_create_balance(*new_balance_owner, *amount);
Ok(Transaction {
id: *transaction_id,
amount: *amount,
})
} else {
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)
.and_then(|_| self.get_balance(&source))
.and_then(|source_balance| {
let total_amount = amount
.checked_add(COST_OF_PUT)
.ok_or(SndError::ExcessiveValue)?;
if !self.has_sufficient_balance(source_balance, total_amount) {
return Err(SndError::InsufficientBalance);
}
self.create_balance(destination, *new_balance_owner)
})
.and_then(|()| {
self.commit_mutation(&source);
self.transfer_coins(source, destination, *amount, *transaction_id)
})
};
Response::Transaction(result)
}
CoinsRequest::GetBalance => {
let coin_balance_id = owner_pk.into();
let result = self
.authorise_operations(&[Operation::GetBalance], coin_balance_id, requester_pk)
.and_then(move |_| self.get_balance(&coin_balance_id));
Response::GetBalance(result)
}
}
}
}