1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use crate::claimable::{BenefitSource, CircuitRole};
use codec::{Decode, Encode};
use frame_support::dispatch::DispatchResult;
use scale_info::TypeInfo;
use sp_runtime::DispatchError;
use sp_std::{fmt::Debug, prelude::*};

pub type ExecutionId = u64;

/// General round information consisting ofindex (one-based), head
/// (beginning block number), and term (round length in number of blocks).
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)]
pub struct Settlement<Account, Balance, AssetId> {
    pub requester: Account,
    pub recipient: Account,
    pub settlement_amount: Balance,
    pub maybe_asset_id: Option<AssetId>,
    pub outcome: Outcome,
    pub source: BenefitSource,
    pub role: CircuitRole,
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)]
pub struct RequestCharge<Account, Balance, AssetId> {
    pub payee: Account,
    pub offered_reward: Balance,
    pub maybe_asset_id: Option<AssetId>,
    pub charge_fee: Balance,
    pub recipient: Option<Account>,
    pub source: BenefitSource,
    pub role: CircuitRole,
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)]
pub enum Outcome {
    UnexpectedFailure,
    Revert,
    Commit,
    Slash,
}

pub trait AccountManager<Account, Balance, Hash, BlockNumber, AssetId> {
    /// Lookup charge by Id and fail if not found
    fn get_charge_or_fail(
        charge_id: Hash,
    ) -> Result<RequestCharge<Account, Balance, AssetId>, DispatchError>;
    /// Lookup charge by Id and fail if not found
    fn no_charge_or_fail(charge_id: Hash) -> Result<(), DispatchError>;
    /// Lookup charge by Id and fail if not found
    fn get_settlement(charge_id: Hash) -> Option<Settlement<Account, Balance, AssetId>>;
    /// Get all settlements by role in the current round
    fn get_settlements_by_role(
        role: CircuitRole,
    ) -> Vec<(Account, Settlement<Account, Balance, AssetId>)>;
    /// Bump contracts registry nonce in Account Manager nonce state and return charge request Id
    fn bump_contracts_registry_nonce() -> Result<Hash, DispatchError>;
    /// Validate deposit goes through
    fn validate_deposit(
        charge_id: Hash,
        request_charge: RequestCharge<Account, Balance, AssetId>,
    ) -> Result<Balance, DispatchError>;
    /// Send batch deposits to a recipient via the escrow
    fn deposit_batch(batch: &[(Hash, RequestCharge<Account, Balance, AssetId>)]) -> DispatchResult;
    /// Send funds to a recipient via the escrow
    fn deposit(
        charge_id: Hash,
        request_charge: RequestCharge<Account, Balance, AssetId>,
    ) -> DispatchResult;
    /// Finalize a transaction, with an optional reason for failures
    fn finalize(
        charge_id: Hash,
        outcome: Outcome,
        maybe_recipient: Option<Account>,
        maybe_actual_fees: Option<Balance>,
    ) -> DispatchResult;
    /// Assert infallible finalize of a transaction if exists
    fn finalize_infallible(charge_id: Hash, outcome: Outcome) -> bool;

    fn cancel_deposit(charge_id: Hash) -> bool;

    fn assign_deposit(charge_id: Hash, recipient: &Account) -> bool;

    fn transfer_deposit(
        charge_id: Hash,
        new_charge_id: Hash,
        new_reward: Option<Balance>,
        new_payee: Option<&Account>,
        new_recipient: Option<&Account>,
    ) -> DispatchResult;

    fn can_withdraw(beneficiary: &Account, amount: Balance, asset_id: Option<AssetId>) -> bool;

    fn deposit_immediately(beneficiary: &Account, amount: Balance, asset_id: Option<AssetId>);

    fn withdraw_immediately(
        beneficiary: &Account,
        amount: Balance,
        asset_id: Option<AssetId>,
    ) -> DispatchResult;
}