create_accounts.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //! Connect to a SQLite-backed ledger and create accounts.
  2. //!
  3. //! Run with:
  4. //! ```sh
  5. //! cargo run -p kuatia --example create_accounts
  6. //! ```
  7. use std::collections::BTreeMap;
  8. use std::sync::Arc;
  9. use kuatia::ledger::Ledger;
  10. use kuatia_core::*;
  11. use kuatia_storage_sql::SqlStore;
  12. #[tokio::main]
  13. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  14. let ledger = connect().await?;
  15. // The common case is one line: a version-1 account.
  16. ledger
  17. .create_account(Account::debit_must_not_exceed_credit(AccountId::new(1)))
  18. .await?;
  19. ledger
  20. .create_account(Account::debit_must_not_exceed_credit(AccountId::new(2)))
  21. .await?;
  22. // A system account (fees, settlement, market-making) — no balance floor.
  23. ledger
  24. .create_account(Account::new(AccountId::new(50)))
  25. .await?;
  26. // The same thing spelled out, so you can see every field of an `Account`.
  27. // This boundary account is where value enters/leaves the ledger.
  28. let external = Account {
  29. id: AccountId::new(99),
  30. version: 1, // accounts always start at version 1
  31. flags: AccountFlags::empty(), // not frozen, not closed
  32. book: DEFAULT_BOOK, // the implicit default book
  33. metadata: BTreeMap::new(), // free-form key/value metadata
  34. };
  35. ledger.create_account(external).await?;
  36. // Read them back (latest version of each).
  37. println!("accounts:");
  38. let mut accounts = ledger.list_accounts().await?;
  39. accounts.sort_by_key(|a| (a.id.id, a.id.sub));
  40. for a in &accounts {
  41. println!(" {:?} flags={:?} v{}", a.id, a.flags, a.version);
  42. }
  43. Ok(())
  44. }
  45. /// Open a fresh in-memory SQLite database, run migrations, and wrap it in a
  46. /// `Ledger`. Point the connection string at a file (e.g.
  47. /// `"sqlite://ledger.db?mode=rwc"`) or a Postgres URL for a persistent ledger.
  48. async fn connect() -> Result<Arc<Ledger>, Box<dyn std::error::Error>> {
  49. sqlx::any::install_default_drivers();
  50. let pool = sqlx::any::AnyPoolOptions::new()
  51. .max_connections(1)
  52. .connect("sqlite::memory:")
  53. .await?;
  54. let store = SqlStore::new(pool);
  55. store.migrate().await?;
  56. let ledger = Arc::new(Ledger::new(store));
  57. // On startup, finish any commit a crash interrupted (idempotent roll-forward).
  58. // A clean store has nothing pending, so this returns 0.
  59. ledger.recover().await?;
  60. Ok(ledger)
  61. }