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
use {
18
    super::*,
19
    parity_scale_codec::DecodeAll,
20
    snowbridge_router_primitives::inbound::{
21
        envelope::Envelope, Command as SnowbridgeCommand, MessageProcessor, MessageV1,
22
    },
23
    sp_runtime::DispatchError,
24
    sp_std::marker::PhantomData,
25
};
26

            
27
/// Generic token message processor to handle both native and foreign token commands, as well as token registration.
28
pub struct GenericTokenMessageProcessor<T, NativeTokenProcessor, ForeignTokenProcessor>(
29
    PhantomData<(T, NativeTokenProcessor, ForeignTokenProcessor)>,
30
);
31

            
32
impl<T, NativeTokenProcessor, ForeignTokenProcessor> MessageProcessor
33
    for GenericTokenMessageProcessor<T, NativeTokenProcessor, ForeignTokenProcessor>
34
where
35
    T: frame_system::Config,
36
    NativeTokenProcessor: MessageProcessor,
37
    ForeignTokenProcessor: MessageProcessor,
38
{
39
17
    fn can_process_message(channel: &Channel, envelope: &Envelope) -> bool {
40
17
        match VersionedXcmMessage::decode_all(&mut envelope.payload.as_slice()) {
41
            Ok(VersionedXcmMessage::V1(MessageV1 {
42
                command: SnowbridgeCommand::SendNativeToken { .. },
43
                ..
44
8
            })) => NativeTokenProcessor::can_process_message(channel, envelope),
45
            Ok(VersionedXcmMessage::V1(MessageV1 {
46
                command: SnowbridgeCommand::SendToken { .. },
47
                ..
48
5
            })) => ForeignTokenProcessor::can_process_message(channel, envelope),
49
            Ok(VersionedXcmMessage::V1(MessageV1 {
50
                command: SnowbridgeCommand::RegisterToken { .. },
51
                ..
52
2
            })) => true,
53
2
            Err(e) => {
54
2
                log::trace!(
55
                    "GenericTokenMessageProcessor: failed to decode message. Error: {:?}",
56
                    e
57
                );
58
2
                false
59
            }
60
        }
61
17
    }
62

            
63
13
    fn process_message(channel: Channel, envelope: Envelope) -> Result<(), DispatchError> {
64
13
        match VersionedXcmMessage::decode_all(&mut envelope.payload.as_slice()) {
65
            Ok(VersionedXcmMessage::V1(MessageV1 {
66
                command: SnowbridgeCommand::SendNativeToken { .. },
67
                ..
68
8
            })) => NativeTokenProcessor::process_message(channel, envelope),
69
            Ok(VersionedXcmMessage::V1(MessageV1 {
70
                command: SnowbridgeCommand::SendToken { .. },
71
                ..
72
3
            })) => ForeignTokenProcessor::process_message(channel, envelope),
73
            Ok(VersionedXcmMessage::V1(MessageV1 {
74
                command: SnowbridgeCommand::RegisterToken { .. },
75
                ..
76
2
            })) => Ok(()),
77
            Err(e) => {
78
                log::trace!(
79
                    "GenericTokenMessageProcessor: failed to process message. Error: {:?}",
80
                    e
81
                );
82
                Ok(())
83
            }
84
        }
85
13
    }
86
}
87

            
88
/// Empty processor to avoid erroring while receiving a specific command (such as SendToken)
89
pub struct NoOpProcessor;
90

            
91
impl MessageProcessor for NoOpProcessor {
92
11
    fn can_process_message(_channel: &Channel, _envelope: &Envelope) -> bool {
93
11
        true
94
11
    }
95

            
96
27
    fn process_message(_channel: Channel, _envelope: Envelope) -> Result<(), DispatchError> {
97
27
        Ok(())
98
27
    }
99
}