1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam 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
// Moonbeam 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 Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! # Encode Module
18
//!
19
//! ## Overview
20
//!
21
//! Module to provide `StakeEncodeCall`, `HrmpEncodeCall` and `UtilityEncodeCall` implementations
22
//! for the Xcm Transactor pallet
23

            
24
use frame_support::pallet_prelude::*;
25
use sp_runtime::traits::{AccountIdLookup, StaticLookup};
26
use sp_std::prelude::*;
27
use xcm_primitives::{
28
	AvailableStakeCalls, HrmpAvailableCalls, HrmpEncodeCall, StakeEncodeCall,
29
	UtilityAvailableCalls, UtilityEncodeCall, XcmTransact,
30
};
31

            
32
pub use crate::pallet::*;
33

            
34
pub use crate::weights::WeightInfo;
35

            
36
impl<T: Config> UtilityEncodeCall for Pallet<T> {
37
47
	fn encode_call<Transactor: XcmTransact>(
38
47
		transactor: Transactor,
39
47
		call: UtilityAvailableCalls,
40
47
	) -> Vec<u8> {
41
47
		let mut encoded_call: Vec<u8> = Vec::new();
42
47
		// pallet index
43
47
		encoded_call.push(transactor.utility_pallet_index());
44
47

            
45
47
		match call {
46
47
			UtilityAvailableCalls::AsDerivative(a, b) => {
47
47
				// call index
48
47
				encoded_call.push(RelayIndices::<T>::get().as_derivative);
49
47
				// encoded argument
50
47
				encoded_call.append(&mut a.encode());
51
47
				encoded_call.append(&mut b.clone());
52
47
			}
53
47
		}
54
47

            
55
47
		encoded_call
56
47
	}
57
}
58

            
59
impl<T: Config> HrmpEncodeCall for Pallet<T> {
60
18
	fn hrmp_encode_call(call: HrmpAvailableCalls) -> Result<Vec<u8>, xcm::latest::Error> {
61
18
		let mut encoded_call: Vec<u8> = Vec::new();
62
18
		// pallet index
63
18
		encoded_call.push(RelayIndices::<T>::get().hrmp);
64
18

            
65
18
		match call {
66
8
			HrmpAvailableCalls::InitOpenChannel(a, b, c) => {
67
8
				// call index
68
8
				encoded_call.push(RelayIndices::<T>::get().init_open_channel);
69
8
				// encoded arguments
70
8
				encoded_call.append(&mut a.encode());
71
8
				encoded_call.append(&mut b.encode());
72
8
				encoded_call.append(&mut c.encode());
73
8
			}
74
5
			HrmpAvailableCalls::AcceptOpenChannel(a) => {
75
5
				// call index
76
5
				encoded_call.push(RelayIndices::<T>::get().accept_open_channel);
77
5
				// encoded argument
78
5
				encoded_call.append(&mut a.encode());
79
5
			}
80
4
			HrmpAvailableCalls::CloseChannel(a) => {
81
4
				// call index
82
4
				encoded_call.push(RelayIndices::<T>::get().close_channel);
83
4
				// encoded argument
84
4
				encoded_call.append(&mut a.encode());
85
4
			}
86
1
			HrmpAvailableCalls::CancelOpenRequest(a, b) => {
87
1
				// call index
88
1
				encoded_call.push(RelayIndices::<T>::get().cancel_open_request);
89
1
				// encoded argument
90
1
				encoded_call.append(&mut a.encode());
91
1
				encoded_call.append(&mut b.encode());
92
1
			}
93
		}
94

            
95
18
		Ok(encoded_call)
96
18
	}
97
}
98

            
99
4
fn encode_compact_arg<T: parity_scale_codec::HasCompact>(input: T) -> Vec<u8> {
100
	#[derive(Encode)]
101
	struct CompactWrapper<T: parity_scale_codec::HasCompact> {
102
		#[codec(compact)]
103
		input: T,
104
	}
105
4
	CompactWrapper { input }.encode()
106
4
}
107

            
108
impl<T: Config> StakeEncodeCall for Pallet<T> {
109
14
	fn encode_call<Transactor: XcmTransact>(
110
14
		transactor: Transactor,
111
14
		call: AvailableStakeCalls,
112
14
	) -> Vec<u8> {
113
14
		let mut encoded_call: Vec<u8> = Vec::new();
114
14
		// pallet index
115
14
		encoded_call.push(transactor.staking_pallet_index());
116
14

            
117
14
		match call {
118
1
			AvailableStakeCalls::Bond(b, c) => {
119
1
				// call index
120
1
				encoded_call.push(RelayIndices::<T>::get().bond);
121
1
				// encoded arguments
122
1
				encoded_call.append(&mut encode_compact_arg(b));
123
1
				encoded_call.append(&mut c.encode());
124
1
			}
125
1
			AvailableStakeCalls::BondExtra(a) => {
126
1
				// call index
127
1
				encoded_call.push(RelayIndices::<T>::get().bond_extra);
128
1
				// encoded argument
129
1
				encoded_call.append(&mut encode_compact_arg(a));
130
1
			}
131
1
			AvailableStakeCalls::Unbond(a) => {
132
1
				// call index
133
1
				encoded_call.push(RelayIndices::<T>::get().unbond);
134
1
				// encoded argument
135
1
				encoded_call.append(&mut encode_compact_arg(a));
136
1
			}
137
1
			AvailableStakeCalls::WithdrawUnbonded(a) => {
138
1
				// call index
139
1
				encoded_call.push(RelayIndices::<T>::get().withdraw_unbonded);
140
1
				// encoded argument
141
1
				encoded_call.append(&mut a.encode());
142
1
			}
143
1
			AvailableStakeCalls::Validate(a) => {
144
1
				// call index
145
1
				encoded_call.push(RelayIndices::<T>::get().validate);
146
1
				// encoded argument
147
1
				encoded_call.append(&mut a.encode());
148
1
			}
149
3
			AvailableStakeCalls::Chill => {
150
3
				// call index
151
3
				encoded_call.push(RelayIndices::<T>::get().chill);
152
3
			}
153
1
			AvailableStakeCalls::SetPayee(a) => {
154
1
				// call index
155
1
				encoded_call.push(RelayIndices::<T>::get().set_payee);
156
1
				// encoded argument
157
1
				encoded_call.append(&mut a.encode());
158
1
			}
159
3
			AvailableStakeCalls::SetController => {
160
3
				// call index
161
3
				encoded_call.push(RelayIndices::<T>::get().set_controller);
162
3
			}
163
1
			AvailableStakeCalls::Rebond(a) => {
164
1
				// call index
165
1
				encoded_call.push(RelayIndices::<T>::get().rebond);
166
1
				// encoded argument
167
1
				encoded_call.append(&mut encode_compact_arg(a));
168
1
			}
169
1
			AvailableStakeCalls::Nominate(a) => {
170
1
				// call index
171
1
				encoded_call.push(RelayIndices::<T>::get().nominate);
172
1
				let nominated: Vec<
173
1
					<AccountIdLookup<sp_runtime::AccountId32, ()> as StaticLookup>::Source,
174
2
				> = a.iter().map(|add| (*add).clone().into()).collect();
175
1
				encoded_call.append(&mut nominated.encode());
176
1
			}
177
		}
178

            
179
14
		encoded_call
180
14
	}
181
}