withdraw.rs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //! Fund an account, then withdraw value out of the ledger.
  2. //!
  3. //! Run with:
  4. //! ```sh
  5. //! cargo run -p kuatia --example withdraw
  6. //! ```
  7. use std::sync::Arc;
  8. use kuatia::ledger::Ledger;
  9. use kuatia_core::*;
  10. use kuatia_storage_sql::SqlStore;
  11. #[tokio::main]
  12. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  13. let ledger = connect().await?;
  14. let alice = AccountId::new(1);
  15. let external = AccountId::new(99);
  16. let usd = AssetId::new(1);
  17. let money = Amount::new(2);
  18. ledger
  19. .create_account(Account::debit_must_not_exceed_credit(alice))
  20. .await?;
  21. ledger.create_account(Account::new(external)).await?;
  22. // Fund Alice with $100.00.
  23. ledger
  24. .commit(
  25. TransferBuilder::new()
  26. .deposit(alice, usd, money.parse("100.00")?, external)?
  27. .build(),
  28. )
  29. .await?;
  30. println!(
  31. "after deposit: alice = {} USD",
  32. money.format(ledger.balance(&alice, &usd).await?)
  33. );
  34. // Withdraw $30.00 from Alice out to the external boundary account.
  35. ledger
  36. .commit(
  37. TransferBuilder::new()
  38. .withdraw(alice, usd, money.parse("30.00")?, external)
  39. .build(),
  40. )
  41. .await?;
  42. println!(
  43. "after withdraw: alice = {} USD",
  44. money.format(ledger.balance(&alice, &usd).await?)
  45. );
  46. // The external account carries the offset (negative) side: the mirror of the
  47. // value that currently sits inside the ledger.
  48. println!(
  49. "external boundary: {} USD",
  50. money.format(ledger.balance(&external, &usd).await?)
  51. );
  52. Ok(())
  53. }
  54. async fn connect() -> Result<Arc<Ledger>, Box<dyn std::error::Error>> {
  55. sqlx::any::install_default_drivers();
  56. let pool = sqlx::any::AnyPoolOptions::new()
  57. .max_connections(1)
  58. .connect("sqlite::memory:")
  59. .await?;
  60. let store = SqlStore::new(pool);
  61. store.migrate().await?;
  62. let ledger = Arc::new(Ledger::new(store));
  63. // On startup, finish any commit a crash interrupted (idempotent roll-forward).
  64. ledger.recover().await?;
  65. Ok(ledger)
  66. }