withdraw.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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::new(alice, AccountPolicy::NoOverdraft))
  20. .await?;
  21. ledger
  22. .create_account(Account::new(external, AccountPolicy::ExternalAccount))
  23. .await?;
  24. // Fund Alice with $100.00.
  25. ledger
  26. .commit(
  27. TransferBuilder::new()
  28. .deposit(alice, usd, money.parse("100.00")?, external)?
  29. .build(),
  30. )
  31. .await?;
  32. println!(
  33. "after deposit: alice = {} USD",
  34. money.format(ledger.balance(&alice, &usd).await?)
  35. );
  36. // Withdraw $30.00 from Alice out to the external boundary account.
  37. ledger
  38. .commit(
  39. TransferBuilder::new()
  40. .withdraw(alice, usd, money.parse("30.00")?, external)
  41. .build(),
  42. )
  43. .await?;
  44. println!(
  45. "after withdraw: alice = {} USD",
  46. money.format(ledger.balance(&alice, &usd).await?)
  47. );
  48. // The external account carries the offset (negative) side: the mirror of the
  49. // value that currently sits inside the ledger.
  50. println!(
  51. "external boundary: {} USD",
  52. money.format(ledger.balance(&external, &usd).await?)
  53. );
  54. Ok(())
  55. }
  56. async fn connect() -> Result<Arc<Ledger>, Box<dyn std::error::Error>> {
  57. sqlx::any::install_default_drivers();
  58. let pool = sqlx::any::AnyPoolOptions::new()
  59. .max_connections(1)
  60. .connect("sqlite::memory:")
  61. .await?;
  62. let store = SqlStore::new(pool);
  63. store.migrate().await?;
  64. let ledger = Arc::new(Ledger::new(store));
  65. // On startup, finish any commit a crash interrupted (idempotent roll-forward).
  66. ledger.recover().await?;
  67. Ok(ledger)
  68. }