ledger.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. use crate::{
  2. amount::AmountCents, storage::Storage, transaction::Type, AccountId, Amount, AssetManager,
  3. Error, Payment, PaymentId, Status, Transaction, TransactionId,
  4. };
  5. use std::{cmp::Ordering, collections::HashMap};
  6. /// The Verax ledger
  7. #[derive(Clone, Debug)]
  8. pub struct Ledger<S>
  9. where
  10. S: Storage + Sync + Send,
  11. {
  12. storage: S,
  13. asset_manager: AssetManager,
  14. }
  15. impl<S> Ledger<S>
  16. where
  17. S: Storage + Sync + Send,
  18. {
  19. /// Creates a new ledger instance
  20. pub fn new(storage: S, asset_manager: AssetManager) -> Self {
  21. Self {
  22. storage,
  23. asset_manager,
  24. }
  25. }
  26. /// Parses a human amount (float amounts serialized as string to avoid precision loss)
  27. pub fn parse_amount(&self, asset: &str, amount: &str) -> Result<Amount, Error> {
  28. self.asset_manager.human_amount_by_name(asset, amount)
  29. }
  30. /// Returns a reference to the asset manager
  31. pub fn asset_manager(&self) -> &AssetManager {
  32. &self.asset_manager
  33. }
  34. /// The internal usage is to select unspent payments for each account to
  35. /// create new transactions. The external API however does not expose that
  36. /// level of usage, instead it exposes a simple API to move funds using
  37. /// accounts to debit from and accounts to credit to. A single transaction
  38. /// can use multiple accounts to debit and credit, instead of a single
  39. /// account.
  40. ///
  41. /// This function selects the unspent payments to be used in a transaction,
  42. /// in a descending order (making sure to include any negative deposit).
  43. ///
  44. /// This function returns a vector of payments to be used as inputs and
  45. /// optionally a dependent transaction to be executed first. This
  46. /// transaction is an internal transaction and it settles immediately. It is
  47. /// used to split an existing payment into two payments, one to be used as
  48. /// input and the other to be used as change. This is done to avoid locking
  49. /// any change amount until the main transaction settles.
  50. async fn select_payments_from_accounts(
  51. &self,
  52. payments: Vec<(AccountId, Amount)>,
  53. ) -> Result<(Option<Transaction>, Vec<Payment>), Error> {
  54. let mut to_spend = HashMap::<_, AmountCents>::new();
  55. for (account_id, amount) in payments.into_iter() {
  56. let id = (account_id, amount.asset().clone());
  57. if let Some(value) = to_spend.get_mut(&id) {
  58. (*value)
  59. .checked_add(amount.cents())
  60. .ok_or(Error::Overflow)?;
  61. } else {
  62. to_spend.insert(id, amount.cents());
  63. }
  64. }
  65. let mut change_input = vec![];
  66. let mut change_output = vec![];
  67. let mut payments: Vec<Payment> = vec![];
  68. for ((account, asset), mut to_spend_cents) in to_spend.into_iter() {
  69. let iterator = self
  70. .storage
  71. .get_unspent_payments(&account, asset.id, to_spend_cents)
  72. .await?;
  73. for payment in iterator.into_iter() {
  74. let cents = payment.amount.cents();
  75. to_spend_cents = to_spend_cents.checked_sub(cents).ok_or(Error::Underflow)?;
  76. payments.push(payment);
  77. match to_spend_cents.cmp(&0) {
  78. Ordering::Equal => {
  79. // No change amount, we are done with this input
  80. break;
  81. }
  82. Ordering::Less => {
  83. // The last input a greater amount than needed, therefore the last payment
  84. // must be split into two payments.
  85. //
  86. // This function ensures the exact amounts are used, to archieve that an
  87. // internal transaction is executed to split this unspent payment into two
  88. // unspent payments. This internal transaction settles immediately.
  89. //
  90. // The alternative would be to use this whole unspent payment but the it
  91. // will mean the exchange amount will not be spendable until the current
  92. // transaction finalizes.
  93. let required_amount = to_spend_cents.abs();
  94. let input = payments
  95. .pop()
  96. .ok_or(Error::InsufficientBalance(account.clone(), asset.id))?;
  97. let change_back =
  98. cents.checked_sub(required_amount).ok_or(Error::Underflow)?;
  99. change_input.push(input);
  100. change_output.push((account.clone(), asset.new_amount(change_back)));
  101. change_output.push((account.clone(), asset.new_amount(required_amount)));
  102. // Go to the next payment
  103. break;
  104. }
  105. _ => {
  106. // We need more funds, continue to the selecting the
  107. // available payment if any
  108. }
  109. }
  110. }
  111. if to_spend_cents > 0 {
  112. // We don't have enough payment to cover the to_spend_cents
  113. // Return an insufficient balance error
  114. return Err(Error::InsufficientBalance(account, asset.id));
  115. }
  116. }
  117. let exchange_tx = if change_input.is_empty() {
  118. None
  119. } else {
  120. let total = change_input.len();
  121. let split_input = Transaction::new(
  122. "Exchange transaction".to_owned(),
  123. // Set the change transaction as settled. This is an
  124. // internal transaction to split existing payments
  125. // into exact new payments, so the main transaction has no
  126. // change.
  127. Status::Settled,
  128. Type::Exchange,
  129. change_input,
  130. change_output,
  131. )
  132. .await?;
  133. for i in 0..total {
  134. #[allow(clippy::arithmetic_side_effects)]
  135. // Spend the new payment
  136. payments.push(split_input.creates()[i * 2].clone());
  137. }
  138. Some(split_input)
  139. };
  140. Ok((exchange_tx, payments))
  141. }
  142. /// Creates a new transaction and returns it.
  143. ///
  144. /// The input is pretty simple, take this amounts from these given accounts
  145. /// and send them to these accounts (and amounts). The job of this function
  146. /// is to figure it out how to do it. This function will make sure that each
  147. /// account has enough balance, selecting the unspent payments from each
  148. /// account that will be spent. It will also return a list of transactions
  149. /// that will be used to return the change to the accounts, these accounts
  150. /// can be settled immediately so no other funds required to perform the
  151. /// transaction are locked.
  152. ///
  153. /// This functions performs read only operations on top of the storage layer
  154. /// and it will guarantee execution (meaning that it will not lock any
  155. /// funds, so these transactions may fail if any selected payment is spent
  156. /// between the time the transaction is created and executed).
  157. ///
  158. /// A NewTransaction struct is returned, the change_transactions should be
  159. /// executed and set as settled before the transaction is executed,
  160. /// otherwise it will fail. A failure in any execution will render the
  161. /// entire operation as failed but no funds will be locked.
  162. pub async fn new_transaction(
  163. &self,
  164. reference: String,
  165. status: Status,
  166. from: Vec<(AccountId, Amount)>,
  167. to: Vec<(AccountId, Amount)>,
  168. ) -> Result<Transaction, Error> {
  169. let (change_transaction, payments) = self.select_payments_from_accounts(from).await?;
  170. if let Some(mut change_tx) = change_transaction {
  171. change_tx.persist(&self.storage).await?;
  172. }
  173. let mut transaction =
  174. Transaction::new(reference, status, Type::Transaction, payments, to).await?;
  175. transaction.persist(&self.storage).await?;
  176. Ok(transaction)
  177. }
  178. /// Return the balances from a given account
  179. ///
  180. /// The balance is a vector of Amounts, one for each asset. The balance will
  181. /// return only spendable amounts, meaning that any amount that is locked in
  182. /// a transaction will not be returned.
  183. ///
  184. /// TODO: Return locked funds as well.
  185. pub async fn get_balance(&self, account: &AccountId) -> Result<Vec<Amount>, Error> {
  186. Ok(self.storage.get_balance(account).await?)
  187. }
  188. /// Creates an external deposit
  189. ///
  190. /// Although a deposit can have multiple output payments, to different
  191. /// accounts and amounts, to keep the upstream API simple, this function
  192. /// only accepts a single account and amount to credit
  193. pub async fn deposit(
  194. &self,
  195. account: &AccountId,
  196. amount: Amount,
  197. status: Status,
  198. reference: String,
  199. ) -> Result<Transaction, Error> {
  200. let mut transaction =
  201. Transaction::new_external_deposit(reference, status, vec![(account.clone(), amount)])?;
  202. transaction.persist(&self.storage).await?;
  203. Ok(transaction)
  204. }
  205. /// Creates a new withdrawal transaction and returns it.
  206. ///
  207. /// Although a transaction supports multiple inputs to be burned, from
  208. /// different accounts, to keep things simple, this function only supports a
  209. /// single input (single account and single amount). This is because the
  210. /// natural behaviour is to have withdrawals from a single account.
  211. pub async fn withdrawal(
  212. &self,
  213. account: &AccountId,
  214. amount: Amount,
  215. status: Status,
  216. reference: String,
  217. ) -> Result<Transaction, Error> {
  218. let (change_transactions, payments) = self
  219. .select_payments_from_accounts(vec![(account.clone(), amount)])
  220. .await?;
  221. for mut change_tx in change_transactions.into_iter() {
  222. change_tx.persist(&self.storage).await?;
  223. }
  224. let mut transaction = Transaction::new_external_withdrawal(reference, status, payments)?;
  225. transaction.persist(&self.storage).await?;
  226. Ok(transaction)
  227. }
  228. /// Returns the payment object by a given payment id
  229. pub async fn get_payment_info(&self, payment_id: &PaymentId) -> Result<Payment, Error> {
  230. Ok(self.storage.get_payment(payment_id).await?)
  231. }
  232. /// Returns the transaction object by a given transaction id
  233. pub async fn get_transaction(
  234. &self,
  235. transaction_id: &TransactionId,
  236. ) -> Result<Transaction, Error> {
  237. Ok(self
  238. .storage
  239. .get_transaction(transaction_id)
  240. .await?
  241. .try_into()?)
  242. }
  243. /// Returns all transactions from a given account. It can be optionally be
  244. /// sorted by transaction type. The transactions are sorted from newest to
  245. /// oldest.
  246. pub async fn get_transactions(
  247. &self,
  248. account_id: &AccountId,
  249. types: Vec<Type>,
  250. ) -> Result<Vec<Transaction>, Error> {
  251. let types = if types.is_empty() {
  252. vec![Type::Transaction, Type::Deposit, Type::Withdrawal]
  253. } else {
  254. types
  255. };
  256. let r = self
  257. .storage
  258. .get_transactions(account_id, &types, &[])
  259. .await?
  260. .into_iter()
  261. .map(|x| x.try_into())
  262. .collect::<Result<Vec<Transaction>, _>>()?;
  263. Ok(r)
  264. }
  265. /// Attempts to change the status of a given transaction id. On success the
  266. /// new transaction object is returned, otherwise an error is returned.
  267. pub async fn change_status(
  268. &self,
  269. transaction_id: &TransactionId,
  270. new_status: Status,
  271. reason: String,
  272. ) -> Result<Transaction, Error> {
  273. let mut tx: Transaction = self
  274. .storage
  275. .get_transaction(transaction_id)
  276. .await?
  277. .try_into()?;
  278. tx.change_status(new_status, reason)?;
  279. tx.persist(&self.storage).await?;
  280. Ok(tx)
  281. }
  282. }