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::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)]
51
pub enum ProviderRequest {
52
960
    Free,
53
8
    StreamPayment { config: StreamConfig },
54
}
55

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

            
63
#[apply(derive_storage_traits)]
64
#[derive(Copy, Serialize, Deserialize, MaxEncodedLen)]
65
pub enum AssignmentWitness {
66
263
    Free,
67
4
    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
183
    fn try_start_assignment(
83
183
        assigner: AccountId,
84
183
        provider: AccountId,
85
183
        request: &Self::ProviderRequest,
86
183
        extra: Self::AssignerParameter,
87
183
    ) -> Result<Self::AssignmentWitness, DispatchErrorWithPostInfo> {
88
183
        let witness = match (request, extra) {
89
175
            (Self::ProviderRequest::Free, Self::AssignerParameter::Free) => {
90
175
                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
4
                )?;
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
179
        Ok(witness)
111
183
    }
112

            
113
12
    fn try_stop_assignment(
114
12
        provider: AccountId,
115
12
        witness: Self::AssignmentWitness,
116
12
    ) -> Result<(), DispatchErrorWithPostInfo> {
117
12
        match witness {
118
12
            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
12
        Ok(())
128
12
    }
129

            
130
    /// Return the values for a free assignment if it is supported.
131
    /// This is required to perform automatic migration from old Bootnodes storage.
132
2
    fn free_variant_values() -> Option<(
133
2
        Self::ProviderRequest,
134
2
        Self::AssignerParameter,
135
2
        Self::AssignmentWitness,
136
2
    )> {
137
2
        Some((
138
2
            Self::ProviderRequest::Free,
139
2
            Self::AssignerParameter::Free,
140
2
            Self::AssignmentWitness::Free,
141
2
        ))
142
2
    }
143

            
144
    // The values returned by the following functions should match with each other.
145
    #[cfg(feature = "runtime-benchmarks")]
146
    fn benchmark_provider_request() -> Self::ProviderRequest {
147
        ProviderRequest::Free
148
    }
149

            
150
    #[cfg(feature = "runtime-benchmarks")]
151
    fn benchmark_assigner_parameter() -> Self::AssignerParameter {
152
        AssignerExtra::Free
153
    }
154

            
155
    #[cfg(feature = "runtime-benchmarks")]
156
    fn benchmark_assignment_witness() -> Self::AssignmentWitness {
157
        AssignmentWitness::Free
158
    }
159
}