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 { length, data }] => Some((b"GeneralKey", *length, *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 },
89 [PalletInstance(instance), GeneralKey { length, data }] => {
90 Some((b"PalletInstance", *instance, b"GeneralKey", *length, *data).encode())
91 },
92
93 [PalletInstance(instance), AccountKey20 { key, .. }] => {
94 Some((b"PalletInstance", *instance, b"AccountKey20", *key).encode())
95 },
96 [PalletInstance(instance), AccountId32 { id, .. }] => {
97 Some((b"PalletInstance", *instance, b"AccountId32", *id).encode())
98 },
99
100 _ => None,
102 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use crate::TokenIdOf;
109 use xcm::{
110 latest::WESTEND_GENESIS_HASH,
111 prelude::{
112 GeneralIndex, GeneralKey, GlobalConsensus, Junction::*, Location, NetworkId::ByGenesis,
113 PalletInstance, Parachain,
114 },
115 };
116 use xcm_executor::traits::ConvertLocation;
117
118 #[test]
119 fn test_token_of_id() {
120 let token_locations = [
121 Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH))]),
124 Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(2000)]),
127 Location::new(
129 1,
130 [
131 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
132 Parachain(2000),
133 GeneralIndex(1),
134 ],
135 ),
136 Location::new(
138 1,
139 [
140 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
141 Parachain(2000),
142 GeneralKey { length: 32, data: [0; 32] },
143 ],
144 ),
145 Location::new(
147 1,
148 [
149 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
150 Parachain(2000),
151 AccountKey20 { network: None, key: [0; 20] },
152 ],
153 ),
154 Location::new(
156 1,
157 [
158 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
159 Parachain(2000),
160 AccountId32 { network: None, id: [0; 32] },
161 ],
162 ),
163 Location::new(
166 1,
167 [
168 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
169 Parachain(2000),
170 PalletInstance(8),
171 ],
172 ),
173 Location::new(
175 1,
176 [
177 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
178 Parachain(2000),
179 PalletInstance(8),
180 GeneralIndex(1),
181 ],
182 ),
183 Location::new(
185 1,
186 [
187 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
188 Parachain(2000),
189 PalletInstance(8),
190 GeneralKey { length: 32, data: [0; 32] },
191 ],
192 ),
193 Location::new(
195 1,
196 [
197 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
198 Parachain(2000),
199 PalletInstance(8),
200 AccountKey20 { network: None, key: [0; 20] },
201 ],
202 ),
203 Location::new(
205 1,
206 [
207 GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
208 Parachain(2000),
209 PalletInstance(8),
210 AccountId32 { network: None, id: [0; 32] },
211 ],
212 ),
213 ];
214
215 for token in token_locations {
216 assert!(
217 TokenIdOf::convert_location(&token).is_some(),
218 "Valid token = {token:?} yields no TokenId."
219 );
220 }
221
222 let non_token_locations = [
223 Location::new(1, []),
225 Location::new(1, [Parachain(1000)]),
227 ];
228
229 for token in non_token_locations {
230 assert!(
231 TokenIdOf::convert_location(&token).is_none(),
232 "Invalid token = {token:?} yields a TokenId."
233 );
234 }
235 }
236}