ledger.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. use crate::{
  2. storage::{Batch, Storage},
  3. transaction::Type,
  4. AccountId, Amount, AssetManager, Error, Payment, Status, Transaction, TransactionId,
  5. };
  6. use std::{cmp::Ordering, collections::HashMap};
  7. #[derive(Clone, Debug)]
  8. pub struct Ledger<'a, B, S>
  9. where
  10. B: Batch<'a>,
  11. S: Storage<'a, B> + Sync + Send,
  12. {
  13. storage: S,
  14. asset_manager: AssetManager,
  15. _phantom: std::marker::PhantomData<&'a B>,
  16. }
  17. impl<'a, B, S> Ledger<'a, B, S>
  18. where
  19. B: Batch<'a>,
  20. S: Storage<'a, B> + Sync + Send,
  21. {
  22. pub fn new(storage: S, asset_manager: AssetManager) -> Self {
  23. Self {
  24. storage,
  25. asset_manager,
  26. _phantom: std::marker::PhantomData,
  27. }
  28. }
  29. pub fn parse_amount(&self, asset: &str, amount: &str) -> Result<Amount, Error> {
  30. Ok(self.asset_manager.human_amount_by_name(asset, amount)?)
  31. }
  32. /// Selects the unspent payments to be used as inputs of the new transaction.
  33. ///
  34. /// This function also returns a list of transactions that will be used as
  35. /// exchanged transactions, to make sure the main transaction doesn't hold
  36. /// extra funds, by splitting any large unspent payments into two, one that
  37. /// matches exactly the needed amount, and another one that will be used as
  38. /// change. These exchange transaction are internal transactions and they
  39. /// are created as settled.
  40. async fn create_inputs_to_pay_from_accounts(
  41. &self,
  42. payments: Vec<(AccountId, Amount)>,
  43. ) -> Result<(Vec<Transaction>, Vec<Payment>), Error> {
  44. let mut to_spend = HashMap::new();
  45. for (account_id, amount) in payments.into_iter() {
  46. let id = (account_id, *amount.asset());
  47. if let Some(value) = to_spend.get_mut(&id) {
  48. *value += amount.cents();
  49. } else {
  50. to_spend.insert(id, amount.cents());
  51. }
  52. }
  53. let mut change_transactions = vec![];
  54. let mut payments: Vec<Payment> = vec![];
  55. for ((account, asset), mut to_spend_cents) in to_spend.into_iter() {
  56. let iterator = self
  57. .storage
  58. .get_unspent_payments(&account, asset.id, to_spend_cents)
  59. .await?;
  60. for payment in iterator.into_iter() {
  61. let cents = payment.amount.cents();
  62. to_spend_cents -= cents;
  63. payments.push(payment);
  64. match to_spend_cents.cmp(&0) {
  65. Ordering::Equal => {
  66. // No change amount, we are done with this input
  67. break;
  68. }
  69. Ordering::Less => {
  70. // There is a change amount, we need to split the last
  71. // input into two payment_ids into the same accounts in
  72. // a transaction that will settle immediately, otherwise
  73. // the change amount will be unspentable until this
  74. // transaction settles. By doing so the current
  75. // operation will have no change and it can safely take
  76. // its time to settle without making any change amount
  77. // unspentable.
  78. let to_spend_cents = to_spend_cents.abs();
  79. let input = payments
  80. .pop()
  81. .ok_or(Error::InsufficientBalance(account.clone(), asset.id))?;
  82. let split_input = Transaction::new(
  83. "Exchange transaction".to_owned(),
  84. // Set the change transaction as settled. This is an
  85. // internal transaction to split an existing payment
  86. // into two. Since this is an internal transaction it
  87. // can be settled immediately.
  88. //
  89. // Because this internal transaction is being settled
  90. // immediately, the other payment can be used right away,
  91. // otherwise it would be locked until the main
  92. // transaction settles.
  93. Status::Settled,
  94. Type::Internal,
  95. vec![input],
  96. vec![
  97. (account.clone(), asset.new_amount(cents - to_spend_cents)),
  98. (account.clone(), asset.new_amount(to_spend_cents)),
  99. ],
  100. )
  101. .await?;
  102. // Spend the new payment
  103. payments.push(split_input.creates()[0].clone());
  104. // Return the split payment transaction to be executed
  105. // later as a pre-requisite for the new transaction
  106. change_transactions.push(split_input);
  107. // Go to the next payment input or exit the loop
  108. break;
  109. }
  110. _ => {
  111. // We need more funds, continue to the selecting the
  112. // available payment if any
  113. }
  114. }
  115. }
  116. if to_spend_cents > 0 {
  117. // We don't have enough payment to cover the to_spend_cents
  118. // Return an insufficient balance error
  119. return Err(Error::InsufficientBalance(account, asset.id));
  120. }
  121. }
  122. Ok((change_transactions, payments))
  123. }
  124. /// Creates a new transaction and returns it.
  125. ///
  126. /// The input is pretty simple, take this amounts from these given accounts
  127. /// and send them to these accounts (and amounts). The job of this function
  128. /// is to figure it out how to do it. This function will make sure that each
  129. /// account has enough balance, selecting the unspent payments from each
  130. /// account that will be spent. It will also return a list of transactions
  131. /// that will be used to return the change to the accounts, these accounts
  132. /// can be settled immediately so no other funds required to perform the
  133. /// transaction are locked.
  134. ///
  135. /// This functions performs read only operations on top of the storage layer
  136. /// and it will guarantee execution (meaning that it will not lock any
  137. /// funds, so these transactions may fail if any selected payment is spent
  138. /// between the time the transaction is created and executed).
  139. ///
  140. /// A NewTransaction struct is returned, the change_transactions should be
  141. /// executed and set as settled before the transaction is executed,
  142. /// otherwise it will fail. A failure in any execution will render the
  143. /// entire operation as failed but no funds will be locked.
  144. pub async fn new_transaction(
  145. &'a self,
  146. reference: String,
  147. status: Status,
  148. from: Vec<(AccountId, Amount)>,
  149. to: Vec<(AccountId, Amount)>,
  150. ) -> Result<Transaction, Error> {
  151. let (change_transactions, payments) = self.create_inputs_to_pay_from_accounts(from).await?;
  152. for mut change_tx in change_transactions.into_iter() {
  153. change_tx.persist(&self.storage).await?;
  154. }
  155. let mut transaction =
  156. Transaction::new(reference, status, Type::Transaction, payments, to).await?;
  157. transaction.persist(&self.storage).await?;
  158. Ok(transaction)
  159. }
  160. /// Return the balances from a given account
  161. ///
  162. /// The balance is a vector of Amounts, one for each asset. The balance will
  163. /// return only spendable amounts, meaning that any amount that is locked in
  164. /// a transaction will not be returned.
  165. ///
  166. /// TODO: Return locked funds as well.
  167. pub async fn get_balance(&self, account: &AccountId) -> Result<Vec<Amount>, Error> {
  168. Ok(self.storage.get_balance(account).await?)
  169. }
  170. pub async fn deposit(
  171. &'a self,
  172. account: &AccountId,
  173. amount: Amount,
  174. status: Status,
  175. reference: String,
  176. ) -> Result<Transaction, Error> {
  177. let mut transaction =
  178. Transaction::new_external_deposit(reference, status, vec![(account.clone(), amount)])?;
  179. println!("{}", serde_json::to_string_pretty(&transaction).unwrap());
  180. transaction.persist(&self.storage).await?;
  181. Ok(transaction)
  182. }
  183. pub async fn withdrawal(
  184. &'a self,
  185. account: &AccountId,
  186. amount: Amount,
  187. status: Status,
  188. reference: String,
  189. ) -> Result<Transaction, Error> {
  190. let (change_transactions, payments) = self
  191. .create_inputs_to_pay_from_accounts(vec![(account.clone(), amount)])
  192. .await?;
  193. for mut change_tx in change_transactions.into_iter() {
  194. change_tx.persist(&self.storage).await?;
  195. }
  196. let mut transaction = Transaction::new_external_withdrawal(reference, status, payments)?;
  197. transaction.persist(&self.storage).await?;
  198. Ok(transaction)
  199. }
  200. /// Returns the transaction object by a given transaction id
  201. pub async fn get_transaction(
  202. &'a self,
  203. transaction_id: &TransactionId,
  204. ) -> Result<Transaction, Error> {
  205. Ok(self
  206. .storage
  207. .get_transaction(transaction_id)
  208. .await?
  209. .try_into()?)
  210. }
  211. /// Returns all transactions from a given account. It can be optionally be
  212. /// sorted by transaction type. The transactions are sorted from newest to
  213. /// oldest.
  214. pub async fn get_transactions(
  215. &'a self,
  216. account_id: &AccountId,
  217. typ: Option<Type>,
  218. ) -> Result<Vec<Transaction>, Error> {
  219. let r = self
  220. .storage
  221. .get_transactions(account_id, typ)
  222. .await?
  223. .into_iter()
  224. .map(|x| x.try_into())
  225. .collect::<Result<Vec<Transaction>, _>>()?;
  226. Ok(r)
  227. }
  228. /// Attemps to change the status of a given transaction id. On success the
  229. /// new transaction object is returned, otherwise an error is returned.
  230. pub async fn change_status(
  231. &'a self,
  232. transaction_id: &TransactionId,
  233. new_status: Status,
  234. ) -> Result<Transaction, Error> {
  235. let mut tx: Transaction = self
  236. .storage
  237. .get_transaction(transaction_id)
  238. .await?
  239. .try_into()?;
  240. tx.change_status(new_status)?;
  241. tx.persist(&self.storage).await?;
  242. Ok(tx)
  243. }
  244. }