use crate::traits::{
ApproveGrant,
ApproveWithoutTransfer,
SpendApprovedGrant,
StartReview,
};
use codec::{
Codec,
Decode,
Encode,
};
use sp_runtime::{
traits::Zero,
RuntimeDebug,
};
use sp_std::prelude::*;
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)]
pub enum BountyMapID {
ApplicationId,
MilestoneId,
}
impl Default for BountyMapID {
fn default() -> BountyMapID {
BountyMapID::ApplicationId
}
}
#[derive(new, PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
pub struct BountyInformation<Poster, Hash, Currency, ReviewBoard> {
poster: Poster,
topic: Hash,
funding_reserved: Currency,
acceptance_committee: ReviewBoard,
supervision_committee: Option<ReviewBoard>,
}
impl<Poster: Clone, Hash: Clone, Currency: Copy, ReviewBoard: Clone>
BountyInformation<Poster, Hash, Currency, ReviewBoard>
{
pub fn poster(&self) -> Poster {
self.poster.clone()
}
pub fn topic(&self) -> Hash {
self.topic.clone()
}
pub fn funding_reserved(&self) -> Currency {
self.funding_reserved
}
pub fn acceptance_committee(&self) -> ReviewBoard {
self.acceptance_committee.clone()
}
pub fn supervision_committee(&self) -> Option<ReviewBoard> {
self.supervision_committee.clone()
}
}
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)]
pub enum ApplicationState<VoteId> {
SubmittedAwaitingResponse,
UnderReviewByAcceptanceCommittee(VoteId),
ApprovedAndLive,
Closed,
}
impl<VoteId: Codec + PartialEq + Zero + From<u32> + Copy>
ApplicationState<VoteId>
{
pub fn awaiting_review(&self) -> bool {
match self {
ApplicationState::SubmittedAwaitingResponse => true,
_ => false,
}
}
pub fn under_review_by_acceptance_committee(self) -> Option<VoteId> {
match self {
ApplicationState::SubmittedAwaitingResponse => None,
ApplicationState::UnderReviewByAcceptanceCommittee(vote_id) => {
Some(vote_id)
}
_ => None,
}
}
pub fn approved_and_live(self) -> bool {
match self {
ApplicationState::ApprovedAndLive => true,
_ => false,
}
}
}
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
pub struct GrantApplication<AccountId, BankId, Currency, Hash, State> {
submitter: AccountId,
bank: Option<BankId>,
description: Hash,
total_amount: Currency,
state: State,
}
impl<
AccountId: Clone + PartialEq,
BankId: Copy,
Currency: Clone,
Hash: Clone,
VoteId: Codec + PartialEq + Zero + From<u32> + Copy,
>
GrantApplication<
AccountId,
BankId,
Currency,
Hash,
ApplicationState<VoteId>,
>
{
pub fn new(
submitter: AccountId,
bank: Option<BankId>,
description: Hash,
total_amount: Currency,
) -> GrantApplication<
AccountId,
BankId,
Currency,
Hash,
ApplicationState<VoteId>,
> {
GrantApplication {
submitter,
bank,
description,
total_amount,
state: ApplicationState::SubmittedAwaitingResponse,
}
}
pub fn submitter(&self) -> AccountId {
self.submitter.clone()
}
pub fn is_submitter(&self, who: &AccountId) -> bool {
&self.submitter == who
}
pub fn submission(&self) -> Hash {
self.description.clone()
}
pub fn bank(&self) -> Option<BankId> {
self.bank
}
pub fn state(&self) -> ApplicationState<VoteId> {
self.state
}
pub fn total_amount(&self) -> Currency {
self.total_amount.clone()
}
}
impl<
AccountId: Clone + PartialEq,
BankId: Copy,
Currency: Clone,
Hash: Clone,
VoteId: Codec + PartialEq + Zero + From<u32> + Copy,
> StartReview<VoteId>
for GrantApplication<
AccountId,
BankId,
Currency,
Hash,
ApplicationState<VoteId>,
>
{
fn start_review(&self, vote_id: VoteId) -> Option<Self> {
match self.state {
ApplicationState::SubmittedAwaitingResponse => {
Some(GrantApplication {
submitter: self.submitter.clone(),
bank: self.bank,
description: self.description.clone(),
total_amount: self.total_amount.clone(),
state: ApplicationState::UnderReviewByAcceptanceCommittee(
vote_id,
),
})
}
_ => None,
}
}
fn get_review_id(&self) -> Option<VoteId> {
match self.state() {
ApplicationState::UnderReviewByAcceptanceCommittee(vote_id) => {
Some(vote_id)
}
_ => None,
}
}
}
impl<
AccountId: Clone + PartialEq,
BankId: Copy,
Currency: Clone,
Hash: Clone,
VoteId: Codec + PartialEq + Zero + From<u32> + Copy,
> ApproveGrant
for GrantApplication<
AccountId,
BankId,
Currency,
Hash,
ApplicationState<VoteId>,
>
{
fn approve_grant(&self) -> Self {
GrantApplication {
submitter: self.submitter.clone(),
bank: self.bank,
description: self.description.clone(),
total_amount: self.total_amount.clone(),
state: ApplicationState::ApprovedAndLive,
}
}
fn grant_approved(&self) -> bool {
match self.state {
ApplicationState::ApprovedAndLive => true,
_ => false,
}
}
}
impl<
AccountId: Clone + PartialEq,
BankId: Copy,
Currency: Copy + sp_std::ops::Sub<Currency, Output = Currency> + PartialOrd,
Hash: Clone,
VoteId: Codec + PartialEq + Zero + From<u32> + Copy,
> SpendApprovedGrant<Currency>
for GrantApplication<
AccountId,
BankId,
Currency,
Hash,
ApplicationState<VoteId>,
>
{
fn spend_approved_grant(&self, amount: Currency) -> Option<Self> {
match self.state {
ApplicationState::ApprovedAndLive => {
if self.total_amount >= amount {
let new_amount = self.total_amount - amount;
Some(GrantApplication {
submitter: self.submitter.clone(),
bank: self.bank,
description: self.description.clone(),
total_amount: new_amount,
state: self.state,
})
} else {
None
}
}
_ => None,
}
}
}
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)]
pub enum MilestoneStatus<VoteId> {
SubmittedAwaitingResponse,
SubmittedReviewStarted(VoteId),
ApprovedButNotTransferred,
ApprovedAndTransferExecuted,
}
impl<VoteId> Default for MilestoneStatus<VoteId> {
fn default() -> MilestoneStatus<VoteId> {
MilestoneStatus::SubmittedAwaitingResponse
}
}
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
pub struct MilestoneSubmission<
AccountId,
ApplicationId,
Hash,
Currency,
MilestoneStatus,
> {
submitter: AccountId,
referenced_application: ApplicationId,
submission: Hash,
amount: Currency,
state: MilestoneStatus,
}
impl<
AccountId: Clone + PartialEq,
ApplicationId: Codec + Copy,
Hash: Clone,
Currency: Copy,
VoteId: Codec + Copy,
>
MilestoneSubmission<
AccountId,
ApplicationId,
Hash,
Currency,
MilestoneStatus<VoteId>,
>
{
pub fn new(
submitter: AccountId,
referenced_application: ApplicationId,
submission: Hash,
amount: Currency,
) -> MilestoneSubmission<
AccountId,
ApplicationId,
Hash,
Currency,
MilestoneStatus<VoteId>,
> {
MilestoneSubmission {
submitter,
referenced_application,
submission,
amount,
state: MilestoneStatus::SubmittedAwaitingResponse,
}
}
pub fn submitter(&self) -> AccountId {
self.submitter.clone()
}
pub fn referenced_application(&self) -> ApplicationId {
self.referenced_application
}
pub fn submission(&self) -> Hash {
self.submission.clone()
}
pub fn amount(&self) -> Currency {
self.amount
}
pub fn state(&self) -> MilestoneStatus<VoteId> {
self.state
}
pub fn set_state(&self, state: MilestoneStatus<VoteId>) -> Self {
MilestoneSubmission {
state,
..self.clone()
}
}
pub fn ready_for_review(&self) -> bool {
match self.state {
MilestoneStatus::SubmittedAwaitingResponse => true,
_ => false,
}
}
}
impl<
AccountId: Clone + PartialEq,
ApplicationId: Codec + Copy,
Hash: Clone,
Currency: Copy,
VoteId: Codec + Copy,
> StartReview<VoteId>
for MilestoneSubmission<
AccountId,
ApplicationId,
Hash,
Currency,
MilestoneStatus<VoteId>,
>
{
fn start_review(&self, vote_id: VoteId) -> Option<Self> {
match self.state {
MilestoneStatus::SubmittedAwaitingResponse => {
Some(MilestoneSubmission {
submitter: self.submitter.clone(),
referenced_application: self.referenced_application,
submission: self.submission.clone(),
amount: self.amount,
state: MilestoneStatus::SubmittedReviewStarted(vote_id),
})
}
_ => None,
}
}
fn get_review_id(&self) -> Option<VoteId> {
match self.state {
MilestoneStatus::SubmittedReviewStarted(vote_id) => Some(vote_id),
_ => None,
}
}
}
impl<
AccountId: Clone + PartialEq,
ApplicationId: Codec + Copy,
Hash: Clone,
Currency: Copy,
VoteId: Codec + Copy,
> ApproveWithoutTransfer
for MilestoneSubmission<
AccountId,
ApplicationId,
Hash,
Currency,
MilestoneStatus<VoteId>,
>
{
fn approve_without_transfer(&self) -> Self {
self.set_state(MilestoneStatus::ApprovedButNotTransferred)
}
}