1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
#![cfg_attr(not(feature = "std"), no_std)]
18

            
19
use core::marker::PhantomData;
20
use frame_support::dispatch::DispatchErrorWithPostInfo;
21
use frame_support::traits::OriginTrait;
22
use frame_support::{Deserialize, Serialize};
23
use parity_scale_codec::{DecodeWithMemTracking, MaxEncodedLen};
24
use primitives::{AccountId, Balance};
25
use tp_stream_payment_common::StreamId;
26
use tp_traits::{apply, derive_storage_traits};
27

            
28
pub type StreamConfig = pallet_stream_payment::StreamConfig<
29
    tp_stream_payment_common::TimeUnit,
30
    tp_stream_payment_common::AssetId,
31
    primitives::Balance,
32
>;
33

            
34
type RuntimeOriginOf<Runtime> = <Runtime as frame_system::Config>::RuntimeOrigin;
35

            
36
tp_traits::alias!(
37
    pub trait RuntimeConfigs:
38
        frame_system::Config<AccountId = AccountId> +
39
        pallet_balances::Config<Balance = Balance> +
40
        pallet_stream_payment::Config<
41
            TimeUnit = tp_stream_payment_common::TimeUnit,
42
            AssetId = tp_stream_payment_common::AssetId,
43
            Balance = Balance,
44
            StreamId = tp_stream_payment_common::StreamId,
45
        > +
46
        pallet_data_preservers::Config
47
);
48

            
49
#[apply(derive_storage_traits)]
50
#[derive(Copy, Serialize, Deserialize, MaxEncodedLen, DecodeWithMemTracking)]
51
pub enum ProviderRequest {
52
    Free,
53
    StreamPayment { config: StreamConfig },
54
}
55

            
56
#[apply(derive_storage_traits)]
57
#[derive(Copy, Serialize, Deserialize, DecodeWithMemTracking)]
58
pub enum AssignerExtra {
59
    Free,
60
    StreamPayment { initial_deposit: Balance },
61
}
62

            
63
#[apply(derive_storage_traits)]
64
#[derive(Copy, Serialize, Deserialize, MaxEncodedLen, DecodeWithMemTracking)]
65
pub enum AssignmentWitness {
66
    Free,
67
    StreamPayment { stream_id: StreamId },
68
}
69

            
70
pub struct AssignmentProcessor<Runtime>(PhantomData<Runtime>);
71

            
72
impl<Runtime: RuntimeConfigs> pallet_data_preservers::AssignmentProcessor<AccountId>
73
    for AssignmentProcessor<Runtime>
74
{
75
    /// Providers requests which kind of payment it accepts.
76
    type ProviderRequest = ProviderRequest;
77
    /// Extra parameter the assigner provides.
78
    type AssignerParameter = AssignerExtra;
79
    /// Represents the successful outcome of the assignment.
80
    type AssignmentWitness = AssignmentWitness;
81

            
82
144
    fn try_start_assignment(
83
144
        assigner: AccountId,
84
144
        provider: AccountId,
85
144
        request: &Self::ProviderRequest,
86
144
        extra: Self::AssignerParameter,
87
144
    ) -> Result<Self::AssignmentWitness, DispatchErrorWithPostInfo> {
88
144
        let witness = match (request, extra) {
89
136
            (Self::ProviderRequest::Free, Self::AssignerParameter::Free) => {
90
136
                Self::AssignmentWitness::Free
91
            }
92
            (
93
4
                Self::ProviderRequest::StreamPayment { config },
94
4
                Self::AssignerParameter::StreamPayment { initial_deposit },
95
            ) => {
96
4
                let stream_id = pallet_stream_payment::Pallet::<Runtime>::open_stream_returns_id(
97
4
                    assigner,
98
4
                    provider,
99
4
                    *config,
100
4
                    initial_deposit,
101
                )?;
102

            
103
4
                Self::AssignmentWitness::StreamPayment { stream_id }
104
            }
105
4
            _ => Err(
106
4
                pallet_data_preservers::Error::<Runtime>::AssignmentPaymentRequestParameterMismatch,
107
4
            )?,
108
        };
109

            
110
140
        Ok(witness)
111
144
    }
112

            
113
    fn try_stop_assignment(
114
        provider: AccountId,
115
        witness: Self::AssignmentWitness,
116
    ) -> Result<(), DispatchErrorWithPostInfo> {
117
        match witness {
118
            Self::AssignmentWitness::Free => (),
119
            Self::AssignmentWitness::StreamPayment { stream_id } => {
120
                pallet_stream_payment::Pallet::<Runtime>::close_stream(
121
                    RuntimeOriginOf::<Runtime>::signed(provider),
122
                    stream_id,
123
                )?;
124
            }
125
        }
126

            
127
        Ok(())
128
    }
129

            
130
    // The values returned by the following functions should match with each other.
131
    #[cfg(feature = "runtime-benchmarks")]
132
    fn benchmark_provider_request() -> Self::ProviderRequest {
133
        ProviderRequest::Free
134
    }
135

            
136
    #[cfg(feature = "runtime-benchmarks")]
137
    fn benchmark_assigner_parameter() -> Self::AssignerParameter {
138
        AssignerExtra::Free
139
    }
140

            
141
    #[cfg(feature = "runtime-benchmarks")]
142
    fn benchmark_assignment_witness() -> Self::AssignmentWitness {
143
        AssignmentWitness::Free
144
    }
145
}