pub trait SendXcm {
type Ticket;
// Required methods
fn validate(
destination: &mut Option<MultiLocation>,
message: &mut Option<Xcm<()>>
) -> SendResult<Self::Ticket>;
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError>;
}
Expand description
Utility for sending an XCM message to a given location.
These can be amalgamated in tuples to form sophisticated routing systems. In tuple format, each
router might return NotApplicable
to pass the execution to the next sender item. Note that
each NotApplicable
might alter the destination and the XCM message for to the next router.
Example
/// A sender that only passes the message through and does nothing.
struct Sender1;
impl SendXcm for Sender1 {
type Ticket = Infallible;
fn validate(_: &mut Option<MultiLocation>, _: &mut Option<Xcm<()>>) -> SendResult<Infallible> {
Err(SendError::NotApplicable)
}
fn deliver(_: Infallible) -> Result<XcmHash, SendError> {
unreachable!()
}
}
/// A sender that accepts a message that has an X2 junction, otherwise stops the routing.
struct Sender2;
impl SendXcm for Sender2 {
type Ticket = ();
fn validate(destination: &mut Option<MultiLocation>, message: &mut Option<Xcm<()>>) -> SendResult<()> {
match destination.as_ref().ok_or(SendError::MissingArgument)? {
MultiLocation { parents: 0, interior: X2(j1, j2) } => Ok(((), MultiAssets::new())),
_ => Err(SendError::Unroutable),
}
}
fn deliver(_: ()) -> Result<XcmHash, SendError> {
Ok([0; 32])
}
}
/// A sender that accepts a message from a parent, passing through otherwise.
struct Sender3;
impl SendXcm for Sender3 {
type Ticket = ();
fn validate(destination: &mut Option<MultiLocation>, message: &mut Option<Xcm<()>>) -> SendResult<()> {
match destination.as_ref().ok_or(SendError::MissingArgument)? {
MultiLocation { parents: 1, interior: Here } => Ok(((), MultiAssets::new())),
_ => Err(SendError::NotApplicable),
}
}
fn deliver(_: ()) -> Result<XcmHash, SendError> {
Ok([0; 32])
}
}
// A call to send via XCM. We don't really care about this.
let call: Vec<u8> = ().encode();
let message = Xcm(vec![Instruction::Transact {
origin_kind: OriginKind::Superuser,
require_weight_at_most: Weight::zero(),
call: call.into(),
}]);
let message_hash = message.using_encoded(sp_io::hashing::blake2_256);
// Sender2 will block this.
assert!(send_xcm::<(Sender1, Sender2, Sender3)>(Parent.into(), message.clone()).is_err());
// Sender3 will catch this.
assert!(send_xcm::<(Sender1, Sender3)>(Parent.into(), message.clone()).is_ok());
Required Associated Types§
Required Methods§
sourcefn validate(
destination: &mut Option<MultiLocation>,
message: &mut Option<Xcm<()>>
) -> SendResult<Self::Ticket>
fn validate( destination: &mut Option<MultiLocation>, message: &mut Option<Xcm<()>> ) -> SendResult<Self::Ticket>
Check whether the given _message
is deliverable to the given _destination
and if so
determine the cost which will be paid by this chain to do so, returning a Validated
token
which can be used to enact delivery.
The destination
and message
must be Some
(or else an error will be returned) and they
may only be consumed if the Err
is not NotApplicable
.
If it is not a destination which can be reached with this type but possibly could by others,
then this MUST return NotApplicable
. Any other error will cause the tuple
implementation to exit early without trying other type fields.