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,
30
};
31

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

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

            
36
impl<T: Config> UtilityEncodeCall for Pallet<T> {
37
41
	fn encode_call(self, call: UtilityAvailableCalls) -> Vec<u8> {
38
41
		match call {
39
41
			UtilityAvailableCalls::AsDerivative(a, b) => {
40
41
				let mut encoded_call: Vec<u8> = Vec::new();
41
41
				// pallet index
42
41
				encoded_call.push(RelayIndices::<T>::get().utility);
43
41
				// call index
44
41
				encoded_call.push(RelayIndices::<T>::get().as_derivative);
45
41
				// encoded argument
46
41
				encoded_call.append(&mut a.encode());
47
41
				encoded_call.append(&mut b.clone());
48
41
				encoded_call
49
41
			}
50
41
		}
51
41
	}
52
}
53

            
54
impl<T: Config> HrmpEncodeCall for Pallet<T> {
55
22
	fn hrmp_encode_call(call: HrmpAvailableCalls) -> Result<Vec<u8>, xcm::latest::Error> {
56
22
		match call {
57
9
			HrmpAvailableCalls::InitOpenChannel(a, b, c) => {
58
9
				let mut encoded_call: Vec<u8> = Vec::new();
59
9
				// pallet index
60
9
				encoded_call.push(RelayIndices::<T>::get().hrmp);
61
9
				// call index
62
9
				encoded_call.push(RelayIndices::<T>::get().init_open_channel);
63
9
				// encoded arguments
64
9
				encoded_call.append(&mut a.encode());
65
9
				encoded_call.append(&mut b.encode());
66
9
				encoded_call.append(&mut c.encode());
67
9
				Ok(encoded_call)
68
			}
69
6
			HrmpAvailableCalls::AcceptOpenChannel(a) => {
70
6
				let mut encoded_call: Vec<u8> = Vec::new();
71
6
				// pallet index
72
6
				encoded_call.push(RelayIndices::<T>::get().hrmp);
73
6
				// call index
74
6
				encoded_call.push(RelayIndices::<T>::get().accept_open_channel);
75
6
				// encoded argument
76
6
				encoded_call.append(&mut a.encode());
77
6
				Ok(encoded_call)
78
			}
79
5
			HrmpAvailableCalls::CloseChannel(a) => {
80
5
				let mut encoded_call: Vec<u8> = Vec::new();
81
5
				// pallet index
82
5
				encoded_call.push(RelayIndices::<T>::get().hrmp);
83
5
				// call index
84
5
				encoded_call.push(RelayIndices::<T>::get().close_channel);
85
5
				// encoded argument
86
5
				encoded_call.append(&mut a.encode());
87
5
				Ok(encoded_call)
88
			}
89
2
			HrmpAvailableCalls::CancelOpenRequest(a, b) => {
90
2
				let mut encoded_call: Vec<u8> = Vec::new();
91
2
				// pallet index
92
2
				encoded_call.push(RelayIndices::<T>::get().hrmp);
93
2
				// call index
94
2
				encoded_call.push(RelayIndices::<T>::get().cancel_open_request);
95
2
				// encoded argument
96
2
				encoded_call.append(&mut a.encode());
97
2
				encoded_call.append(&mut b.encode());
98
2
				Ok(encoded_call)
99
			}
100
		}
101
22
	}
102
}
103

            
104
8
fn encode_compact_arg<T: parity_scale_codec::HasCompact>(input: T) -> Vec<u8> {
105
	#[derive(Encode)]
106
	struct CompactWrapper<T: parity_scale_codec::HasCompact> {
107
		#[codec(compact)]
108
		input: T,
109
	}
110
8
	CompactWrapper { input }.encode()
111
8
}
112

            
113
impl<T: Config> StakeEncodeCall for Pallet<T> {
114
24
	fn encode_call(call: AvailableStakeCalls) -> Vec<u8> {
115
24
		match call {
116
2
			AvailableStakeCalls::Bond(b, c) => {
117
2
				let mut encoded_call: Vec<u8> = Vec::new();
118
2
				// pallet index
119
2
				encoded_call.push(RelayIndices::<T>::get().staking);
120
2
				// call index
121
2
				encoded_call.push(RelayIndices::<T>::get().bond);
122
2
				// encoded arguments
123
2
				encoded_call.append(&mut encode_compact_arg(b));
124
2
				encoded_call.append(&mut c.encode());
125
2
				encoded_call
126
			}
127

            
128
2
			AvailableStakeCalls::BondExtra(a) => {
129
2
				let mut encoded_call: Vec<u8> = Vec::new();
130
2
				// pallet index
131
2
				encoded_call.push(RelayIndices::<T>::get().staking);
132
2
				// call index
133
2
				encoded_call.push(RelayIndices::<T>::get().bond_extra);
134
2
				// encoded argument
135
2
				encoded_call.append(&mut encode_compact_arg(a));
136
2
				encoded_call
137
			}
138

            
139
2
			AvailableStakeCalls::Unbond(a) => {
140
2
				let mut encoded_call: Vec<u8> = Vec::new();
141
2
				// pallet index
142
2
				encoded_call.push(RelayIndices::<T>::get().staking);
143
2
				// call index
144
2
				encoded_call.push(RelayIndices::<T>::get().unbond);
145
2
				// encoded argument
146
2
				encoded_call.append(&mut encode_compact_arg(a));
147
2
				encoded_call
148
			}
149

            
150
2
			AvailableStakeCalls::WithdrawUnbonded(a) => {
151
2
				let mut encoded_call: Vec<u8> = Vec::new();
152
2
				// pallet index
153
2
				encoded_call.push(RelayIndices::<T>::get().staking);
154
2
				// call index
155
2
				encoded_call.push(RelayIndices::<T>::get().withdraw_unbonded);
156
2
				// encoded argument
157
2
				encoded_call.append(&mut a.encode());
158
2
				encoded_call
159
			}
160

            
161
2
			AvailableStakeCalls::Validate(a) => {
162
2
				let mut encoded_call: Vec<u8> = Vec::new();
163
2
				// pallet index
164
2
				encoded_call.push(RelayIndices::<T>::get().staking);
165
2
				// call index
166
2
				encoded_call.push(RelayIndices::<T>::get().validate);
167
2
				// encoded argument
168
2
				encoded_call.append(&mut a.encode());
169
2
				encoded_call
170
			}
171

            
172
			AvailableStakeCalls::Chill => {
173
4
				let mut encoded_call: Vec<u8> = Vec::new();
174
4
				// pallet index
175
4
				encoded_call.push(RelayIndices::<T>::get().staking);
176
4
				// call index
177
4
				encoded_call.push(RelayIndices::<T>::get().chill);
178
4
				encoded_call
179
			}
180

            
181
2
			AvailableStakeCalls::SetPayee(a) => {
182
2
				let mut encoded_call: Vec<u8> = Vec::new();
183
2
				// pallet index
184
2
				encoded_call.push(RelayIndices::<T>::get().staking);
185
2
				// call index
186
2
				encoded_call.push(RelayIndices::<T>::get().set_payee);
187
2
				// encoded argument
188
2
				encoded_call.append(&mut a.encode());
189
2
				encoded_call
190
			}
191

            
192
			AvailableStakeCalls::SetController => {
193
4
				let mut encoded_call: Vec<u8> = Vec::new();
194
4
				// pallet index
195
4
				encoded_call.push(RelayIndices::<T>::get().staking);
196
4
				// call index
197
4
				encoded_call.push(RelayIndices::<T>::get().set_controller);
198
4
				encoded_call
199
			}
200

            
201
2
			AvailableStakeCalls::Rebond(a) => {
202
2
				let mut encoded_call: Vec<u8> = Vec::new();
203
2
				// pallet index
204
2
				encoded_call.push(RelayIndices::<T>::get().staking);
205
2
				// call index
206
2
				encoded_call.push(RelayIndices::<T>::get().rebond);
207
2
				// encoded argument
208
2
				encoded_call.append(&mut encode_compact_arg(a));
209
2
				encoded_call
210
			}
211

            
212
2
			AvailableStakeCalls::Nominate(a) => {
213
2
				let mut encoded_call: Vec<u8> = Vec::new();
214
2
				// pallet index
215
2
				encoded_call.push(RelayIndices::<T>::get().staking);
216
2
				// call index
217
2
				encoded_call.push(RelayIndices::<T>::get().nominate);
218
2
				let nominated: Vec<
219
2
					<AccountIdLookup<sp_runtime::AccountId32, ()> as StaticLookup>::Source,
220
3
				> = a.iter().map(|add| (*add).clone().into()).collect();
221
2
				encoded_call.append(&mut nominated.encode());
222
2
				encoded_call
223
			}
224
		}
225
24
	}
226
}