use tracing::trace;
use super::{
account::TAccount, transaction::Transaction, utils::debug_assert_accounting_equation,
AccountId, TransactionAccounting,
};
use crate::{
types::{Error, MarginCurrency},
Result,
};
const N_ACCOUNTS: usize = 6;
pub const USER_WALLET_ACCOUNT: usize = 0;
pub const USER_ORDER_MARGIN_ACCOUNT: usize = 1;
pub const USER_POSITION_MARGIN_ACCOUNT: usize = 2;
pub const EXCHANGE_FEE_ACCOUNT: usize = 3;
pub const BROKER_MARGIN_ACCOUNT: usize = 4;
pub const TREASURY_ACCOUNT: usize = 5;
#[derive(Debug)]
pub struct InMemoryTransactionAccounting<M>
where
M: MarginCurrency,
{
margin_accounts: [TAccount<M>; N_ACCOUNTS],
}
impl<M> TransactionAccounting<M> for InMemoryTransactionAccounting<M>
where
M: MarginCurrency,
{
fn new(user_starting_wallet_balance: M) -> Self {
let mut s = Self {
margin_accounts: [TAccount::default(); N_ACCOUNTS],
};
s.margin_accounts[USER_WALLET_ACCOUNT].post_debit(user_starting_wallet_balance);
s.margin_accounts[TREASURY_ACCOUNT].post_credit(user_starting_wallet_balance);
debug_assert_accounting_equation(&s.margin_accounts);
s
}
fn create_margin_transfer(&mut self, transaction: Transaction<M>) -> Result<()> {
trace!("create_margin_transfer: {transaction:?}");
let mut debit_account = self
.margin_accounts
.get(transaction.debit_account_id())
.cloned()
.ok_or(Error::AccountLookupFailure)?;
let credit_account = self
.margin_accounts
.get_mut(transaction.credit_account_id())
.ok_or(Error::AccountLookupFailure)?;
let amnt = transaction.amount();
debit_account.post_debit(amnt);
credit_account.post_credit(amnt);
self.margin_accounts[transaction.debit_account_id()] = debit_account;
debug_assert_accounting_equation(&self.margin_accounts);
Ok(())
}
fn margin_balance_of(&self, account: AccountId) -> Result<M> {
self.margin_accounts
.get(account)
.ok_or(Error::AccountLookupFailure)
.map(|account| account.net_balance())
}
}