1use super::{Junctions, MultiLocation};
20use crate::{
21 v4::{Junction as NewJunction, NetworkId as NewNetworkId},
22 VersionedLocation,
23};
24use bounded_collections::{BoundedSlice, BoundedVec, ConstU32};
25use codec::{self, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
26use scale_info::TypeInfo;
27use serde::{Deserialize, Serialize};
28
29#[derive(
34 Copy,
35 Clone,
36 Eq,
37 PartialEq,
38 Ord,
39 PartialOrd,
40 Encode,
41 Decode,
42 DecodeWithMemTracking,
43 Debug,
44 TypeInfo,
45 MaxEncodedLen,
46 Serialize,
47 Deserialize,
48)]
49#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
50#[scale_info(replace_segment("staging_xcm", "xcm"))]
51pub enum NetworkId {
52 ByGenesis([u8; 32]),
54 ByFork { block_number: u64, block_hash: [u8; 32] },
56 Polkadot,
58 Kusama,
60 Westend,
62 Rococo,
64 Wococo,
66 Ethereum {
68 #[codec(compact)]
70 chain_id: u64,
71 },
72 BitcoinCore,
74 BitcoinCash,
76 PolkadotBulletin,
78}
79
80impl From<NewNetworkId> for Option<NetworkId> {
81 fn from(new: NewNetworkId) -> Self {
82 Some(NetworkId::from(new))
83 }
84}
85
86impl From<NewNetworkId> for NetworkId {
87 fn from(new: NewNetworkId) -> Self {
88 use NewNetworkId::*;
89 match new {
90 ByGenesis(hash) => Self::ByGenesis(hash),
91 ByFork { block_number, block_hash } => Self::ByFork { block_number, block_hash },
92 Polkadot => Self::Polkadot,
93 Kusama => Self::Kusama,
94 Westend => Self::Westend,
95 Rococo => Self::Rococo,
96 Wococo => Self::Wococo,
97 Ethereum { chain_id } => Self::Ethereum { chain_id },
98 BitcoinCore => Self::BitcoinCore,
99 BitcoinCash => Self::BitcoinCash,
100 PolkadotBulletin => Self::PolkadotBulletin,
101 }
102 }
103}
104
105#[derive(
107 Copy,
108 Clone,
109 Eq,
110 PartialEq,
111 Ord,
112 PartialOrd,
113 Encode,
114 Decode,
115 DecodeWithMemTracking,
116 Debug,
117 TypeInfo,
118 MaxEncodedLen,
119 Serialize,
120 Deserialize,
121)]
122#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
123#[scale_info(replace_segment("staging_xcm", "xcm"))]
124pub enum BodyId {
125 Unit,
127 Moniker([u8; 4]),
129 Index(#[codec(compact)] u32),
131 Executive,
133 Technical,
135 Legislative,
138 Judicial,
141 Defense,
144 Administration,
147 Treasury,
150}
151
152#[derive(
154 Copy,
155 Clone,
156 Eq,
157 PartialEq,
158 Ord,
159 PartialOrd,
160 Encode,
161 Decode,
162 DecodeWithMemTracking,
163 Debug,
164 TypeInfo,
165 MaxEncodedLen,
166 Serialize,
167 Deserialize,
168)]
169#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
170#[scale_info(replace_segment("staging_xcm", "xcm"))]
171pub enum BodyPart {
172 Voice,
174 Members {
176 #[codec(compact)]
177 count: u32,
178 },
179 Fraction {
181 #[codec(compact)]
182 nom: u32,
183 #[codec(compact)]
184 denom: u32,
185 },
186 AtLeastProportion {
188 #[codec(compact)]
189 nom: u32,
190 #[codec(compact)]
191 denom: u32,
192 },
193 MoreThanProportion {
195 #[codec(compact)]
196 nom: u32,
197 #[codec(compact)]
198 denom: u32,
199 },
200}
201
202impl BodyPart {
203 pub fn is_majority(&self) -> bool {
205 match self {
206 BodyPart::Fraction { nom, denom } if *nom * 2 > *denom => true,
207 BodyPart::AtLeastProportion { nom, denom } if *nom * 2 > *denom => true,
208 BodyPart::MoreThanProportion { nom, denom } if *nom * 2 >= *denom => true,
209 _ => false,
210 }
211 }
212}
213
214#[derive(
218 Copy,
219 Clone,
220 Eq,
221 PartialEq,
222 Ord,
223 PartialOrd,
224 Encode,
225 Decode,
226 DecodeWithMemTracking,
227 Debug,
228 TypeInfo,
229 MaxEncodedLen,
230 Serialize,
231 Deserialize,
232)]
233#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
234#[scale_info(replace_segment("staging_xcm", "xcm"))]
235pub enum Junction {
236 Parachain(#[codec(compact)] u32),
240 AccountId32 { network: Option<NetworkId>, id: [u8; 32] },
245 AccountIndex64 {
250 network: Option<NetworkId>,
251 #[codec(compact)]
252 index: u64,
253 },
254 AccountKey20 { network: Option<NetworkId>, key: [u8; 20] },
259 PalletInstance(u8),
264 GeneralIndex(#[codec(compact)] u128),
270 GeneralKey { length: u8, data: [u8; 32] },
279 OnlyChild,
283 Plurality { id: BodyId, part: BodyPart },
288 GlobalConsensus(NetworkId),
291}
292
293impl From<NetworkId> for Junction {
294 fn from(n: NetworkId) -> Self {
295 Self::GlobalConsensus(n)
296 }
297}
298
299impl From<[u8; 32]> for Junction {
300 fn from(id: [u8; 32]) -> Self {
301 Self::AccountId32 { network: None, id }
302 }
303}
304
305impl From<BoundedVec<u8, ConstU32<32>>> for Junction {
306 fn from(key: BoundedVec<u8, ConstU32<32>>) -> Self {
307 key.as_bounded_slice().into()
308 }
309}
310
311impl<'a> From<BoundedSlice<'a, u8, ConstU32<32>>> for Junction {
312 fn from(key: BoundedSlice<'a, u8, ConstU32<32>>) -> Self {
313 let mut data = [0u8; 32];
314 data[..key.len()].copy_from_slice(&key[..]);
315 Self::GeneralKey { length: key.len() as u8, data }
316 }
317}
318
319impl<'a> TryFrom<&'a Junction> for BoundedSlice<'a, u8, ConstU32<32>> {
320 type Error = ();
321 fn try_from(key: &'a Junction) -> Result<Self, ()> {
322 match key {
323 Junction::GeneralKey { length, data } =>
324 BoundedSlice::try_from(&data[..data.len().min(*length as usize)]).map_err(|_| ()),
325 _ => Err(()),
326 }
327 }
328}
329
330impl From<[u8; 20]> for Junction {
331 fn from(key: [u8; 20]) -> Self {
332 Self::AccountKey20 { network: None, key }
333 }
334}
335
336impl From<u64> for Junction {
337 fn from(index: u64) -> Self {
338 Self::AccountIndex64 { network: None, index }
339 }
340}
341
342impl From<u128> for Junction {
343 fn from(id: u128) -> Self {
344 Self::GeneralIndex(id)
345 }
346}
347
348impl TryFrom<NewJunction> for Junction {
349 type Error = ();
350
351 fn try_from(value: NewJunction) -> Result<Self, Self::Error> {
352 use NewJunction::*;
353 Ok(match value {
354 Parachain(id) => Self::Parachain(id),
355 AccountId32 { network: maybe_network, id } =>
356 Self::AccountId32 { network: maybe_network.map(|network| network.into()), id },
357 AccountIndex64 { network: maybe_network, index } =>
358 Self::AccountIndex64 { network: maybe_network.map(|network| network.into()), index },
359 AccountKey20 { network: maybe_network, key } =>
360 Self::AccountKey20 { network: maybe_network.map(|network| network.into()), key },
361 PalletInstance(index) => Self::PalletInstance(index),
362 GeneralIndex(id) => Self::GeneralIndex(id),
363 GeneralKey { length, data } => Self::GeneralKey { length, data },
364 OnlyChild => Self::OnlyChild,
365 Plurality { id, part } => Self::Plurality { id, part },
366 GlobalConsensus(network) => Self::GlobalConsensus(network.into()),
367 })
368 }
369}
370
371impl Junction {
372 pub const fn into_location(self) -> MultiLocation {
376 MultiLocation { parents: 0, interior: Junctions::X1(self) }
377 }
378
379 pub const fn into_exterior(self, n: u8) -> MultiLocation {
384 MultiLocation { parents: n, interior: Junctions::X1(self) }
385 }
386
387 pub const fn into_versioned(self) -> VersionedLocation {
391 self.into_location().into_versioned()
392 }
393
394 pub fn remove_network_id(&mut self) {
396 use Junction::*;
397 match self {
398 AccountId32 { ref mut network, .. } |
399 AccountIndex64 { ref mut network, .. } |
400 AccountKey20 { ref mut network, .. } => *network = None,
401 _ => {},
402 }
403 }
404}