pub use polkadot_parachain_primitives::primitives::{
Id as ParaId, IsSystem, Sibling as SiblingParaId,
};
pub use sp_core::U256;
use codec::Encode;
use sp_core::H256;
use sp_std::prelude::*;
use xcm::prelude::{
AccountId32, AccountKey20, GeneralIndex, GeneralKey, GlobalConsensus, Location, PalletInstance,
};
use xcm_builder::{
DescribeAllTerminal, DescribeFamily, DescribeLocation, DescribeTerminus, HashedDescription,
};
pub type AgentId = H256;
#[allow(deprecated)]
pub type AgentIdOf =
HashedDescription<AgentId, (DescribeHere, DescribeFamily<DescribeAllTerminal>)>;
pub type TokenId = H256;
pub type TokenIdOf = HashedDescription<
TokenId,
DescribeGlobalPrefix<(DescribeTerminus, DescribeFamily<DescribeTokenTerminal>)>,
>;
#[deprecated(note = "Use DescribeTerminus from xcm-builder instead.")]
pub struct DescribeHere;
#[allow(deprecated)]
impl DescribeLocation for DescribeHere {
fn describe_location(l: &Location) -> Option<Vec<u8>> {
match l.unpack() {
(0, []) => Some(Vec::<u8>::new().encode()),
_ => None,
}
}
}
pub struct DescribeGlobalPrefix<DescribeInterior>(sp_std::marker::PhantomData<DescribeInterior>);
impl<Suffix: DescribeLocation> DescribeLocation for DescribeGlobalPrefix<Suffix> {
fn describe_location(l: &Location) -> Option<Vec<u8>> {
match (l.parent_count(), l.first_interior()) {
(1, Some(GlobalConsensus(network))) => {
let mut tail = l.clone().split_first_interior().0;
tail.dec_parent();
let interior = Suffix::describe_location(&tail)?;
Some((b"GlobalConsensus", network, interior).encode())
},
_ => None,
}
}
}
pub struct DescribeTokenTerminal;
impl DescribeLocation for DescribeTokenTerminal {
fn describe_location(l: &Location) -> Option<Vec<u8>> {
match l.unpack().1 {
[] => Some(Vec::<u8>::new().encode()),
[GeneralIndex(index)] => Some((b"GeneralIndex", *index).encode()),
[GeneralKey { data, .. }] => Some((b"GeneralKey", *data).encode()),
[AccountKey20 { key, .. }] => Some((b"AccountKey20", *key).encode()),
[AccountId32 { id, .. }] => Some((b"AccountId32", *id).encode()),
[PalletInstance(instance)] => Some((b"PalletInstance", *instance).encode()),
[PalletInstance(instance), GeneralIndex(index)] =>
Some((b"PalletInstance", *instance, b"GeneralIndex", *index).encode()),
[PalletInstance(instance), GeneralKey { data, .. }] =>
Some((b"PalletInstance", *instance, b"GeneralKey", *data).encode()),
[PalletInstance(instance), AccountKey20 { key, .. }] =>
Some((b"PalletInstance", *instance, b"AccountKey20", *key).encode()),
[PalletInstance(instance), AccountId32 { id, .. }] =>
Some((b"PalletInstance", *instance, b"AccountId32", *id).encode()),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use crate::TokenIdOf;
use xcm::{
latest::WESTEND_GENESIS_HASH,
prelude::{
GeneralIndex, GeneralKey, GlobalConsensus, Junction::*, Location, NetworkId::ByGenesis,
PalletInstance, Parachain,
},
};
use xcm_executor::traits::ConvertLocation;
#[test]
fn test_token_of_id() {
let token_locations = [
Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH))]),
Location::new(1, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(2000)]),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
GeneralIndex(1),
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
GeneralKey { length: 32, data: [0; 32] },
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
AccountKey20 { network: None, key: [0; 20] },
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
AccountId32 { network: None, id: [0; 32] },
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
PalletInstance(8),
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
PalletInstance(8),
GeneralIndex(1),
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
PalletInstance(8),
GeneralKey { length: 32, data: [0; 32] },
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
PalletInstance(8),
AccountKey20 { network: None, key: [0; 20] },
],
),
Location::new(
1,
[
GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)),
Parachain(2000),
PalletInstance(8),
AccountId32 { network: None, id: [0; 32] },
],
),
];
for token in token_locations {
assert!(
TokenIdOf::convert_location(&token).is_some(),
"Valid token = {token:?} yeilds no TokenId."
);
}
let non_token_locations = [
Location::new(1, []),
Location::new(1, [Parachain(1000)]),
];
for token in non_token_locations {
assert!(
TokenIdOf::convert_location(&token).is_none(),
"Invalid token = {token:?} yeilds a TokenId."
);
}
}
}