snowbridge_test_utils/
mock_xcm.rs1use codec::Encode;
5use core::cell::RefCell;
6use xcm::prelude::*;
7use xcm_executor::{
8 traits::{FeeManager, FeeReason, TransactAsset},
9 AssetsInHolding,
10};
11
12thread_local! {
13 pub static IS_WAIVED: RefCell<Vec<FeeReason>> = RefCell::new(vec![]);
14 pub static SENDER_OVERRIDE: RefCell<Option<(
15 fn(
16 &mut Option<Location>,
17 &mut Option<Xcm<()>>,
18 ) -> Result<(Xcm<()>, Assets), SendError>,
19 fn(
20 Xcm<()>,
21 ) -> Result<XcmHash, SendError>,
22 )>> = RefCell::new(None);
23 pub static CHARGE_FEES_OVERRIDE: RefCell<Option<
24 fn(Location, Assets) -> xcm::latest::Result
25 >> = RefCell::new(None);
26}
27
28#[allow(dead_code)]
29pub fn set_fee_waiver(waived: Vec<FeeReason>) {
30 IS_WAIVED.with(|l| l.replace(waived));
31}
32
33#[allow(dead_code)]
34pub fn set_sender_override(
35 validate: fn(&mut Option<Location>, &mut Option<Xcm<()>>) -> SendResult<Xcm<()>>,
36 deliver: fn(Xcm<()>) -> Result<XcmHash, SendError>,
37) {
38 SENDER_OVERRIDE.with(|x| x.replace(Some((validate, deliver))));
39}
40
41#[allow(dead_code)]
42pub fn clear_sender_override() {
43 SENDER_OVERRIDE.with(|x| x.replace(None));
44}
45
46#[allow(dead_code)]
47pub fn set_charge_fees_override(charge_fees: fn(Location, Assets) -> xcm::latest::Result) {
48 CHARGE_FEES_OVERRIDE.with(|x| x.replace(Some(charge_fees)));
49}
50
51#[allow(dead_code)]
52pub fn clear_charge_fees_override() {
53 CHARGE_FEES_OVERRIDE.with(|x| x.replace(None));
54}
55
56pub struct MockXcmSender;
58
59impl SendXcm for MockXcmSender {
60 type Ticket = Xcm<()>;
61
62 fn validate(
63 dest: &mut Option<Location>,
64 xcm: &mut Option<Xcm<()>>,
65 ) -> SendResult<Self::Ticket> {
66 let r: SendResult<Self::Ticket> = SENDER_OVERRIDE.with(|s| {
67 if let Some((ref f, _)) = &*s.borrow() {
68 f(dest, xcm)
69 } else {
70 Ok((xcm.take().unwrap(), Assets::default()))
71 }
72 });
73 r
74 }
75
76 fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
77 let r: Result<XcmHash, SendError> = SENDER_OVERRIDE.with(|s| {
78 if let Some((_, ref f)) = &*s.borrow() {
79 f(ticket)
80 } else {
81 let hash = ticket.using_encoded(sp_core::hashing::blake2_256);
82 Ok(hash)
83 }
84 });
85 r
86 }
87}
88
89pub struct SuccessfulTransactor;
91impl TransactAsset for SuccessfulTransactor {
92 fn can_check_in(_origin: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
93 Ok(())
94 }
95
96 fn can_check_out(_dest: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
97 Ok(())
98 }
99
100 fn deposit_asset(_what: &Asset, _who: &Location, _context: Option<&XcmContext>) -> XcmResult {
101 Ok(())
102 }
103
104 fn withdraw_asset(
105 _what: &Asset,
106 _who: &Location,
107 _context: Option<&XcmContext>,
108 ) -> Result<AssetsInHolding, XcmError> {
109 Ok(AssetsInHolding::default())
110 }
111
112 fn internal_transfer_asset(
113 _what: &Asset,
114 _from: &Location,
115 _to: &Location,
116 _context: &XcmContext,
117 ) -> Result<AssetsInHolding, XcmError> {
118 Ok(AssetsInHolding::default())
119 }
120}
121
122pub enum Weightless {}
123impl PreparedMessage for Weightless {
124 fn weight_of(&self) -> Weight {
125 unreachable!();
126 }
127}
128
129pub struct MockXcmExecutor;
131impl<C> ExecuteXcm<C> for MockXcmExecutor {
132 type Prepared = Weightless;
133 fn prepare(_: Xcm<C>, _: Weight) -> Result<Self::Prepared, InstructionError> {
134 unreachable!()
135 }
136 fn execute(_: impl Into<Location>, _: Self::Prepared, _: &mut XcmHash, _: Weight) -> Outcome {
137 unreachable!()
138 }
139 fn charge_fees(location: impl Into<Location>, assets: Assets) -> xcm::latest::Result {
140 let r: xcm::latest::Result = CHARGE_FEES_OVERRIDE.with(|s| {
141 if let Some(ref f) = &*s.borrow() {
142 f(location.into(), assets)
143 } else {
144 Ok(())
145 }
146 });
147 r
148 }
149}
150
151impl FeeManager for MockXcmExecutor {
152 fn is_waived(_: Option<&Location>, r: FeeReason) -> bool {
153 IS_WAIVED.with(|l| l.borrow().contains(&r))
154 }
155
156 fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) {}
157}