1use alloc::vec::Vec;
20use frame_support::{
21 parameter_types,
22 traits::{Contains, CrateVersion, PalletInfoData, PalletsInfoAccess},
23};
24pub use xcm::latest::{prelude::*, Weight};
25use xcm_executor::traits::{ClaimAssets, DropAssets, VersionChangeNotifier};
26pub use xcm_executor::{
27 traits::{
28 AssetExchange, AssetLock, ConvertOrigin, Enact, LockError, OnResponse, TransactAsset,
29 },
30 AssetsInHolding, Config,
31};
32
33parameter_types! {
34 pub static SubscriptionRequests: Vec<(Location, Option<(QueryId, Weight)>)> = vec![];
35 pub static MaxAssetsIntoHolding: u32 = 4;
36}
37
38pub struct TestSubscriptionService;
39
40impl VersionChangeNotifier for TestSubscriptionService {
41 fn start(
42 location: &Location,
43 query_id: QueryId,
44 max_weight: Weight,
45 _context: &XcmContext,
46 ) -> XcmResult {
47 let mut r = SubscriptionRequests::get();
48 r.push((location.clone(), Some((query_id, max_weight))));
49 SubscriptionRequests::set(r);
50 Ok(())
51 }
52 fn stop(location: &Location, _context: &XcmContext) -> XcmResult {
53 let mut r = SubscriptionRequests::get();
54 r.retain(|(l, _q)| l != location);
55 r.push((location.clone(), None));
56 SubscriptionRequests::set(r);
57 Ok(())
58 }
59 fn is_subscribed(location: &Location) -> bool {
60 let r = SubscriptionRequests::get();
61 r.iter().any(|(l, q)| l == location && q.is_some())
62 }
63}
64
65parameter_types! {
66 pub static TrappedAssets: Vec<(Location, Assets)> = vec![];
67}
68
69pub struct TestAssetTrap;
70
71impl DropAssets for TestAssetTrap {
72 fn drop_assets(origin: &Location, assets: AssetsInHolding, _context: &XcmContext) -> Weight {
73 let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
74 t.push((origin.clone(), assets.into()));
75 TrappedAssets::set(t);
76 Weight::from_parts(5, 5)
77 }
78}
79
80impl ClaimAssets for TestAssetTrap {
81 fn claim_assets(
82 origin: &Location,
83 ticket: &Location,
84 what: &Assets,
85 _context: &XcmContext,
86 ) -> bool {
87 let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
88 if let (0, [GeneralIndex(i)]) = ticket.unpack() {
89 if let Some((l, a)) = t.get(*i as usize) {
90 if l == origin && a == what {
91 t.swap_remove(*i as usize);
92 TrappedAssets::set(t);
93 return true
94 }
95 }
96 }
97 false
98 }
99}
100
101pub struct TestAssetExchanger;
102
103impl AssetExchange for TestAssetExchanger {
104 fn exchange_asset(
105 _origin: Option<&Location>,
106 _give: AssetsInHolding,
107 want: &Assets,
108 _maximal: bool,
109 ) -> Result<AssetsInHolding, AssetsInHolding> {
110 Ok(want.clone().into())
111 }
112
113 fn quote_exchange_price(give: &Assets, _want: &Assets, _maximal: bool) -> Option<Assets> {
114 Some(give.clone())
115 }
116}
117
118pub struct TestPalletsInfo;
119impl PalletsInfoAccess for TestPalletsInfo {
120 fn count() -> usize {
121 2
122 }
123 fn infos() -> Vec<PalletInfoData> {
124 vec![
125 PalletInfoData {
126 index: 0,
127 name: "System",
128 module_name: "pallet_system",
129 crate_version: CrateVersion { major: 1, minor: 10, patch: 1 },
130 },
131 PalletInfoData {
132 index: 1,
133 name: "Balances",
134 module_name: "pallet_balances",
135 crate_version: CrateVersion { major: 1, minor: 42, patch: 69 },
136 },
137 ]
138 }
139}
140
141pub struct TestUniversalAliases;
142impl Contains<(Location, Junction)> for TestUniversalAliases {
143 fn contains(aliases: &(Location, Junction)) -> bool {
144 &aliases.0 == &Here.into_location() && &aliases.1 == &GlobalConsensus(ByGenesis([0; 32]))
145 }
146}
147
148parameter_types! {
149 pub static LockedAssets: Vec<(Location, Asset)> = vec![];
150}
151
152pub struct TestLockTicket(Location, Asset);
153impl Enact for TestLockTicket {
154 fn enact(self) -> Result<(), LockError> {
155 let mut locked_assets = LockedAssets::get();
156 locked_assets.push((self.0, self.1));
157 LockedAssets::set(locked_assets);
158 Ok(())
159 }
160}
161pub struct TestUnlockTicket(Location, Asset);
162impl Enact for TestUnlockTicket {
163 fn enact(self) -> Result<(), LockError> {
164 let mut locked_assets = LockedAssets::get();
165 if let Some((idx, _)) = locked_assets
166 .iter()
167 .enumerate()
168 .find(|(_, (origin, asset))| origin == &self.0 && asset == &self.1)
169 {
170 locked_assets.remove(idx);
171 }
172 LockedAssets::set(locked_assets);
173 Ok(())
174 }
175}
176pub struct TestReduceTicket;
177impl Enact for TestReduceTicket {
178 fn enact(self) -> Result<(), LockError> {
179 Ok(())
180 }
181}
182
183pub struct TestAssetLocker;
184impl AssetLock for TestAssetLocker {
185 type LockTicket = TestLockTicket;
186 type UnlockTicket = TestUnlockTicket;
187 type ReduceTicket = TestReduceTicket;
188
189 fn prepare_lock(
190 unlocker: Location,
191 asset: Asset,
192 _owner: Location,
193 ) -> Result<TestLockTicket, LockError> {
194 Ok(TestLockTicket(unlocker, asset))
195 }
196
197 fn prepare_unlock(
198 unlocker: Location,
199 asset: Asset,
200 _owner: Location,
201 ) -> Result<TestUnlockTicket, LockError> {
202 Ok(TestUnlockTicket(unlocker, asset))
203 }
204
205 fn note_unlockable(
206 _locker: Location,
207 _asset: Asset,
208 _owner: Location,
209 ) -> Result<(), LockError> {
210 Ok(())
211 }
212
213 fn prepare_reduce_unlockable(
214 _locker: Location,
215 _asset: Asset,
216 _owner: Location,
217 ) -> Result<TestReduceTicket, LockError> {
218 Ok(TestReduceTicket)
219 }
220}