use crate::param::{AccountGroupId, AccountId, Asset};
use crate::storage::{self, StorageBuilder};
use super::{AccountControl, AccountGroups, AccountGroupsHandle, Accounts, GroupLookup};
pub(crate) struct AccountStateSnapshot<StorageFactory>
where
StorageFactory: storage::LockingPolicyFactory + storage::CreateStorageFor<AccountId> + 'static,
{
accounts: Option<Accounts<StorageFactory>>,
account: AccountId,
group: Option<AccountGroupId>,
}
impl<StorageFactory> Clone for AccountStateSnapshot<StorageFactory>
where
StorageFactory: storage::LockingPolicyFactory + storage::CreateStorageFor<AccountId> + 'static,
{
fn clone(&self) -> Self {
Self {
accounts: self.accounts.clone(),
account: self.account,
group: self.group,
}
}
}
impl<StorageFactory> AccountStateSnapshot<StorageFactory>
where
StorageFactory: storage::LockingPolicyFactory + storage::CreateStorageFor<AccountId> + 'static,
{
pub(crate) fn with_rollback<R>(
&self,
operation: impl FnOnce(Option<AccountGroupId>, Option<Asset>) -> R,
) -> R {
let Some(accounts) = self.accounts.as_ref() else {
return operation(self.group, None);
};
accounts.with_state_rollback(|| {
let account_group = accounts.group_of(self.account);
let account_currency = accounts.currency_of_in_group(self.account, account_group);
operation(account_group, account_currency)
})
}
}
pub struct AccountAdjustmentContext<StorageFactory>
where
StorageFactory: storage::LockingPolicyFactory + storage::CreateStorageFor<AccountId> + 'static,
{
pub account_control: AccountControl<StorageFactory>,
accounts: Option<Accounts<StorageFactory>>,
account: AccountId,
group_lookup: GroupLookup<StorageFactory>,
}
impl<StorageFactory> AccountAdjustmentContext<StorageFactory>
where
StorageFactory: storage::LockingPolicyFactory + storage::CreateStorageFor<AccountId> + 'static,
{
pub(crate) fn with_groups(
account_control: AccountControl<StorageFactory>,
account_groups: AccountGroupsHandle<StorageFactory>,
account: AccountId,
) -> Self {
Self {
account_control,
accounts: None,
account,
group_lookup: GroupLookup::new(account_groups, Some(account)),
}
}
pub(crate) fn with_accounts(
account_control: AccountControl<StorageFactory>,
accounts: Accounts<StorageFactory>,
account_groups: AccountGroupsHandle<StorageFactory>,
account: AccountId,
) -> Self {
Self {
account_control,
accounts: Some(accounts),
account,
group_lookup: GroupLookup::new(account_groups, Some(account)),
}
}
pub fn new(account_control: AccountControl<StorageFactory>, account: AccountId) -> Self
where
StorageFactory: Default,
{
let builder = StorageBuilder::new(StorageFactory::default());
let handle = AccountGroupsHandle::from_inner(StorageFactory::new_shared(
AccountGroups::new(&builder),
));
Self::with_groups(account_control, handle, account)
}
pub fn account_group(&self) -> Option<AccountGroupId> {
self.group_lookup.group()
}
pub(crate) fn state_account_group(&self) -> Option<AccountGroupId> {
self.accounts.as_ref().map_or_else(
|| self.group_lookup.group(),
|accounts| accounts.group_of(self.account),
)
}
pub(crate) fn account_currency(&self, account_group: Option<AccountGroupId>) -> Option<Asset> {
self.accounts
.as_ref()
.and_then(|accounts| accounts.currency_of_in_group(self.account, account_group))
}
pub(crate) fn with_state_writer<R>(&self, operation: impl FnOnce() -> R) -> R {
match self.accounts.as_ref() {
Some(accounts) => accounts.with_state_writer(operation),
None => operation(),
}
}
pub(crate) fn with_state_writer_bypassing_transition<R>(
&self,
operation: impl FnOnce() -> R,
) -> R {
match self.accounts.as_ref() {
Some(accounts) => accounts.with_state_rollback(operation),
None => operation(),
}
}
pub(crate) fn state_snapshot(&self) -> AccountStateSnapshot<StorageFactory> {
AccountStateSnapshot {
accounts: self.accounts.clone(),
account: self.account,
group: self.state_account_group(),
}
}
#[cfg(test)]
pub(crate) fn new_test(account_control: AccountControl<StorageFactory>) -> Self
where
StorageFactory: Default,
{
Self::new(account_control, AccountId::from_u64(0))
}
}