1pub use polkadot_parachain_primitives::primitives::{
8 Id as ParaId, IsSystem, Sibling as SiblingParaId,
9};
10pub use sp_core::U256;
11
12use codec::Encode;
13use sp_core::H256;
14use sp_std::prelude::*;
15use xcm::prelude::{
16 AccountId32, AccountKey20, GeneralIndex, GeneralKey, GlobalConsensus, Location, PalletInstance,
17};
18use xcm_builder::{
19 DescribeAllTerminal, DescribeFamily, DescribeLocation, DescribeTerminus, HashedDescription,
20};
21
22pub type AgentId = H256;
23
24pub type AgentIdOf = HashedDescription<
28 AgentId,
29 (
30 DescribeHere,
31 DescribeFamily<DescribeAllTerminal>,
32 DescribeGlobalPrefix<(DescribeTerminus, DescribeFamily<DescribeTokenTerminal>)>,
33 ),
34>;
35
36pub type TokenId = H256;
37
38pub type TokenIdOf = HashedDescription<
41 TokenId,
42 DescribeGlobalPrefix<(DescribeTerminus, DescribeFamily<DescribeTokenTerminal>)>,
43>;
44
45pub struct DescribeHere;
50#[allow(deprecated)]
51impl DescribeLocation for DescribeHere {
52 fn describe_location(l: &Location) -> Option<Vec<u8>> {
53 match l.unpack() {
54 (0, []) => Some(Vec::<u8>::new().encode()),
55 _ => None,
56 }
57 }
58}
59pub struct DescribeGlobalPrefix<DescribeInterior>(sp_std::marker::PhantomData<DescribeInterior>);
60impl<Suffix: DescribeLocation> DescribeLocation for DescribeGlobalPrefix<Suffix> {
61 fn describe_location(l: &Location) -> Option<Vec<u8>> {
62 match (l.parent_count(), l.first_interior()) {
63 (1, Some(GlobalConsensus(network))) => {
64 let mut tail = l.clone().split_first_interior().0;
65 tail.dec_parent();
66 let interior = Suffix::describe_location(&tail)?;
67 Some((b"GlobalConsensus", network, interior).encode())
68 },
69 _ => None,
70 }
71 }
72}
73
74pub struct DescribeTokenTerminal;
75impl DescribeLocation for DescribeTokenTerminal {
76 fn describe_location(l: &Location) -> Option<Vec<u8>> {
77 match l.unpack().1 {
78 [] => Some(Vec::<u8>::new().encode()),
79 [GeneralIndex(index)] => Some((b"GeneralIndex", *index).encode()),
80 [GeneralKey { data, .. }] => Some((b"GeneralKey", *data).encode()),
81 [AccountKey20 { key, .. }] => Some((b"AccountKey20", *key).encode()),
82 [AccountId32 { id, .. }] => Some((b"AccountId32", *id).encode()),
83
84 [PalletInstance(instance)] => Some((b"PalletInstance", *instance).encode()),
86 [PalletInstance(instance), GeneralIndex(index)] =>
87 Some((b"PalletInstance", *instance, b"GeneralIndex", *index).encode()),
88 [PalletInstance(instance), GeneralKey { data, .. }] =>
89 Some((b"PalletInstance", *instance, b"GeneralKey", *data).encode()),
90
91 [PalletInstance(instance), AccountKey20 { key, .. }] =>
92 Some((b"PalletInstance", *instance, b"AccountKey20", *key).encode()),
93 [PalletInstance(instance), AccountId32 { id, .. }] =>
94 Some((b"PalletInstance", *instance, b"AccountId32", *id).encode()),
95
96 _ => None,
98 }
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use crate::TokenIdOf;
105 use xcm::{
106 latest::WESTEND_GENESIS_HASH,
107 prelude::{
108 GeneralIndex, GeneralKey, GlobalConsensus, Junction::*, Location, NetworkId::ByGenesis,
109 PalletInstance, Parachain,
110 },
111 };
112 use xcm_executor::traits::ConvertLocation;
113
114 #[test]
115 fn test_token_of_id() {
116 let token_locations = [
117 Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH))]),
120 Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(2000)]),
123 Location::new(
125 1,
126 [
127 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
128 Parachain(2000),
129 GeneralIndex(1),
130 ],
131 ),
132 Location::new(
134 1,
135 [
136 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
137 Parachain(2000),
138 GeneralKey { length: 32, data: [0; 32] },
139 ],
140 ),
141 Location::new(
143 1,
144 [
145 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
146 Parachain(2000),
147 AccountKey20 { network: None, key: [0; 20] },
148 ],
149 ),
150 Location::new(
152 1,
153 [
154 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
155 Parachain(2000),
156 AccountId32 { network: None, id: [0; 32] },
157 ],
158 ),
159 Location::new(
162 1,
163 [
164 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
165 Parachain(2000),
166 PalletInstance(8),
167 ],
168 ),
169 Location::new(
171 1,
172 [
173 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
174 Parachain(2000),
175 PalletInstance(8),
176 GeneralIndex(1),
177 ],
178 ),
179 Location::new(
181 1,
182 [
183 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
184 Parachain(2000),
185 PalletInstance(8),
186 GeneralKey { length: 32, data: [0; 32] },
187 ],
188 ),
189 Location::new(
191 1,
192 [
193 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
194 Parachain(2000),
195 PalletInstance(8),
196 AccountKey20 { network: None, key: [0; 20] },
197 ],
198 ),
199 Location::new(
201 1,
202 [
203 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
204 Parachain(2000),
205 PalletInstance(8),
206 AccountId32 { network: None, id: [0; 32] },
207 ],
208 ),
209 ];
210
211 for token in token_locations {
212 assert!(
213 TokenIdOf::convert_location(&token).is_some(),
214 "Valid token = {token:?} yields no TokenId."
215 );
216 }
217
218 let non_token_locations = [
219 Location::new(1, []),
221 Location::new(1, [Parachain(1000)]),
223 ];
224
225 for token in non_token_locations {
226 assert!(
227 TokenIdOf::convert_location(&token).is_none(),
228 "Invalid token = {token:?} yields a TokenId."
229 );
230 }
231 }
232}