mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Fungibles adapter and MultiLocation::X8 (#2662)
* Fungibles adapter and MultiLocation::X8 * Comments * Comment & whitespace * Fix up CI/CD for the new labels. * Fix labels * Whitespace * Fixes * Update Cargo.lock * Update xcm/xcm-builder/src/fungibles_adapter.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Generated
+1
@@ -11134,6 +11134,7 @@ name = "xcm-builder"
|
||||
version = "0.8.30"
|
||||
dependencies = [
|
||||
"frame-support",
|
||||
"impl-trait-for-tuples",
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain",
|
||||
"sp-arithmetic",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
@@ -48,14 +48,22 @@ use crate::VersionedMultiLocation;
|
||||
pub enum MultiLocation {
|
||||
/// The interpreting consensus system.
|
||||
Null,
|
||||
/// A relative path comprising one junction.
|
||||
/// A relative path comprising 1 junction.
|
||||
X1(Junction),
|
||||
/// A relative path comprising two junctions.
|
||||
/// A relative path comprising 2 junctions.
|
||||
X2(Junction, Junction),
|
||||
/// A relative path comprising three junctions.
|
||||
/// A relative path comprising 3 junctions.
|
||||
X3(Junction, Junction, Junction),
|
||||
/// A relative path comprising four junctions.
|
||||
/// A relative path comprising 4 junctions.
|
||||
X4(Junction, Junction, Junction, Junction),
|
||||
/// A relative path comprising 5 junctions.
|
||||
X5(Junction, Junction, Junction, Junction, Junction),
|
||||
/// A relative path comprising 6 junctions.
|
||||
X6(Junction, Junction, Junction, Junction, Junction, Junction),
|
||||
/// A relative path comprising 7 junctions.
|
||||
X7(Junction, Junction, Junction, Junction, Junction, Junction, Junction),
|
||||
/// A relative path comprising 8 junctions.
|
||||
X8(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction),
|
||||
}
|
||||
|
||||
impl From<Junction> for MultiLocation {
|
||||
@@ -89,6 +97,26 @@ impl From<(Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||
MultiLocation::X4(x.0, x.1, x.2, x.3)
|
||||
}
|
||||
}
|
||||
impl From<(Junction, Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||
fn from(x: (Junction, Junction, Junction, Junction, Junction)) -> Self {
|
||||
MultiLocation::X5(x.0, x.1, x.2, x.3, x.4)
|
||||
}
|
||||
}
|
||||
impl From<(Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||
fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction)) -> Self {
|
||||
MultiLocation::X6(x.0, x.1, x.2, x.3, x.4, x.5)
|
||||
}
|
||||
}
|
||||
impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||
fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction)) -> Self {
|
||||
MultiLocation::X7(x.0, x.1, x.2, x.3, x.4, x.5, x.6)
|
||||
}
|
||||
}
|
||||
impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||
fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction)) -> Self {
|
||||
MultiLocation::X8(x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[Junction; 0]> for MultiLocation {
|
||||
fn from(_: [Junction; 0]) -> Self {
|
||||
@@ -119,6 +147,30 @@ impl From<[Junction; 4]> for MultiLocation {
|
||||
MultiLocation::X4(x0, x1, x2, x3)
|
||||
}
|
||||
}
|
||||
impl From<[Junction; 5]> for MultiLocation {
|
||||
fn from(x: [Junction; 5]) -> Self {
|
||||
let [x0, x1, x2, x3, x4] = x;
|
||||
MultiLocation::X5(x0, x1, x2, x3, x4)
|
||||
}
|
||||
}
|
||||
impl From<[Junction; 6]> for MultiLocation {
|
||||
fn from(x: [Junction; 6]) -> Self {
|
||||
let [x0, x1, x2, x3, x4, x5] = x;
|
||||
MultiLocation::X6(x0, x1, x2, x3, x4, x5)
|
||||
}
|
||||
}
|
||||
impl From<[Junction; 7]> for MultiLocation {
|
||||
fn from(x: [Junction; 7]) -> Self {
|
||||
let [x0, x1, x2, x3, x4, x5, x6] = x;
|
||||
MultiLocation::X7(x0, x1, x2, x3, x4, x5, x6)
|
||||
}
|
||||
}
|
||||
impl From<[Junction; 8]> for MultiLocation {
|
||||
fn from(x: [Junction; 8]) -> Self {
|
||||
let [x0, x1, x2, x3, x4, x5, x6, x7] = x;
|
||||
MultiLocation::X8(x0, x1, x2, x3, x4, x5, x6, x7)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MultiLocationIterator(MultiLocation);
|
||||
impl Iterator for MultiLocationIterator {
|
||||
@@ -164,6 +216,10 @@ impl MultiLocation {
|
||||
MultiLocation::X2(ref a, ..) => Some(a),
|
||||
MultiLocation::X3(ref a, ..) => Some(a),
|
||||
MultiLocation::X4(ref a, ..) => Some(a),
|
||||
MultiLocation::X5(ref a, ..) => Some(a),
|
||||
MultiLocation::X6(ref a, ..) => Some(a),
|
||||
MultiLocation::X7(ref a, ..) => Some(a),
|
||||
MultiLocation::X8(ref a, ..) => Some(a),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +231,10 @@ impl MultiLocation {
|
||||
MultiLocation::X2(.., ref a) => Some(a),
|
||||
MultiLocation::X3(.., ref a) => Some(a),
|
||||
MultiLocation::X4(.., ref a) => Some(a),
|
||||
MultiLocation::X5(.., ref a) => Some(a),
|
||||
MultiLocation::X6(.., ref a) => Some(a),
|
||||
MultiLocation::X7(.., ref a) => Some(a),
|
||||
MultiLocation::X8(.., ref a) => Some(a),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +247,10 @@ impl MultiLocation {
|
||||
MultiLocation::X2(a, b) => (MultiLocation::X1(b), Some(a)),
|
||||
MultiLocation::X3(a, b, c) => (MultiLocation::X2(b, c), Some(a)),
|
||||
MultiLocation::X4(a, b, c ,d) => (MultiLocation::X3(b, c, d), Some(a)),
|
||||
MultiLocation::X5(a, b, c ,d, e) => (MultiLocation::X4(b, c, d, e), Some(a)),
|
||||
MultiLocation::X6(a, b, c ,d, e, f) => (MultiLocation::X5(b, c, d, e, f), Some(a)),
|
||||
MultiLocation::X7(a, b, c ,d, e, f, g) => (MultiLocation::X6(b, c, d, e, f, g), Some(a)),
|
||||
MultiLocation::X8(a, b, c ,d, e, f, g, h) => (MultiLocation::X7(b, c, d, e, f, g, h), Some(a)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +263,10 @@ impl MultiLocation {
|
||||
MultiLocation::X2(a, b) => (MultiLocation::X1(a), Some(b)),
|
||||
MultiLocation::X3(a, b, c) => (MultiLocation::X2(a, b), Some(c)),
|
||||
MultiLocation::X4(a, b, c ,d) => (MultiLocation::X3(a, b, c), Some(d)),
|
||||
MultiLocation::X5(a, b, c, d, e) => (MultiLocation::X4(a, b, c, d), Some(e)),
|
||||
MultiLocation::X6(a, b, c, d, e, f) => (MultiLocation::X5(a, b, c, d, e), Some(f)),
|
||||
MultiLocation::X7(a, b, c, d, e, f, g) => (MultiLocation::X6(a, b, c, d, e, f), Some(g)),
|
||||
MultiLocation::X8(a, b, c, d, e, f, g, h) => (MultiLocation::X7(a, b, c, d, e, f, g), Some(h)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +296,10 @@ impl MultiLocation {
|
||||
MultiLocation::X1(a) => MultiLocation::X2(a, new),
|
||||
MultiLocation::X2(a, b) => MultiLocation::X3(a, b, new),
|
||||
MultiLocation::X3(a, b, c) => MultiLocation::X4(a, b, c, new),
|
||||
MultiLocation::X4(a, b, c, d) => MultiLocation::X5(a, b, c, d, new),
|
||||
MultiLocation::X5(a, b, c, d, e) => MultiLocation::X6(a, b, c, d, e, new),
|
||||
MultiLocation::X6(a, b, c, d, e, f) => MultiLocation::X7(a, b, c, d, e, f, new),
|
||||
MultiLocation::X7(a, b, c, d, e, f, g) => MultiLocation::X8(a, b, c, d, e, f, g, new),
|
||||
s => Err(s)?,
|
||||
})
|
||||
}
|
||||
@@ -240,6 +312,10 @@ impl MultiLocation {
|
||||
MultiLocation::X1(a) => MultiLocation::X2(new, a),
|
||||
MultiLocation::X2(a, b) => MultiLocation::X3(new, a, b),
|
||||
MultiLocation::X3(a, b, c) => MultiLocation::X4(new, a, b, c),
|
||||
MultiLocation::X4(a, b, c, d) => MultiLocation::X5(new, a, b, c, d),
|
||||
MultiLocation::X5(a, b, c, d, e) => MultiLocation::X6(new, a, b, c, d, e),
|
||||
MultiLocation::X6(a, b, c, d, e, f) => MultiLocation::X7(new, a, b, c, d, e, f),
|
||||
MultiLocation::X7(a, b, c, d, e, f, g) => MultiLocation::X8(new, a, b, c, d, e, f, g),
|
||||
s => Err(s)?,
|
||||
})
|
||||
}
|
||||
@@ -252,6 +328,10 @@ impl MultiLocation {
|
||||
MultiLocation::X2(..) => 2,
|
||||
MultiLocation::X3(..) => 3,
|
||||
MultiLocation::X4(..) => 4,
|
||||
MultiLocation::X5(..) => 5,
|
||||
MultiLocation::X6(..) => 6,
|
||||
MultiLocation::X7(..) => 7,
|
||||
MultiLocation::X8(..) => 8,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,12 +342,38 @@ impl MultiLocation {
|
||||
(0, MultiLocation::X2(ref a, ..)) => a,
|
||||
(0, MultiLocation::X3(ref a, ..)) => a,
|
||||
(0, MultiLocation::X4(ref a, ..)) => a,
|
||||
(0, MultiLocation::X5(ref a, ..)) => a,
|
||||
(0, MultiLocation::X6(ref a, ..)) => a,
|
||||
(0, MultiLocation::X7(ref a, ..)) => a,
|
||||
(0, MultiLocation::X8(ref a, ..)) => a,
|
||||
(1, MultiLocation::X2(_, ref a)) => a,
|
||||
(1, MultiLocation::X3(_, ref a, ..)) => a,
|
||||
(1, MultiLocation::X4(_, ref a, ..)) => a,
|
||||
(1, MultiLocation::X5(_, ref a, ..)) => a,
|
||||
(1, MultiLocation::X6(_, ref a, ..)) => a,
|
||||
(1, MultiLocation::X7(_, ref a, ..)) => a,
|
||||
(1, MultiLocation::X8(_, ref a, ..)) => a,
|
||||
(2, MultiLocation::X3(_, _, ref a)) => a,
|
||||
(2, MultiLocation::X4(_, _, ref a, ..)) => a,
|
||||
(2, MultiLocation::X5(_, _, ref a, ..)) => a,
|
||||
(2, MultiLocation::X6(_, _, ref a, ..)) => a,
|
||||
(2, MultiLocation::X7(_, _, ref a, ..)) => a,
|
||||
(2, MultiLocation::X8(_, _, ref a, ..)) => a,
|
||||
(3, MultiLocation::X4(_, _, _, ref a)) => a,
|
||||
(3, MultiLocation::X5(_, _, _, ref a, ..)) => a,
|
||||
(3, MultiLocation::X6(_, _, _, ref a, ..)) => a,
|
||||
(3, MultiLocation::X7(_, _, _, ref a, ..)) => a,
|
||||
(3, MultiLocation::X8(_, _, _, ref a, ..)) => a,
|
||||
(4, MultiLocation::X5(_, _, _, _, ref a)) => a,
|
||||
(4, MultiLocation::X6(_, _, _, _, ref a, ..)) => a,
|
||||
(4, MultiLocation::X7(_, _, _, _, ref a, ..)) => a,
|
||||
(4, MultiLocation::X8(_, _, _, _, ref a, ..)) => a,
|
||||
(5, MultiLocation::X6(_, _, _, _, _, ref a)) => a,
|
||||
(5, MultiLocation::X7(_, _, _, _, _, ref a, ..)) => a,
|
||||
(5, MultiLocation::X8(_, _, _, _, _, ref a, ..)) => a,
|
||||
(6, MultiLocation::X7(_, _, _, _, _, _, ref a)) => a,
|
||||
(6, MultiLocation::X8(_, _, _, _, _, _, ref a, ..)) => a,
|
||||
(7, MultiLocation::X8(_, _, _, _, _, _, _, ref a)) => a,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -280,12 +386,38 @@ impl MultiLocation {
|
||||
(0, MultiLocation::X2(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X3(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X4(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X5(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X6(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X7(ref mut a, ..)) => a,
|
||||
(0, MultiLocation::X8(ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X2(_, ref mut a)) => a,
|
||||
(1, MultiLocation::X3(_, ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X4(_, ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X5(_, ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X6(_, ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X7(_, ref mut a, ..)) => a,
|
||||
(1, MultiLocation::X8(_, ref mut a, ..)) => a,
|
||||
(2, MultiLocation::X3(_, _, ref mut a)) => a,
|
||||
(2, MultiLocation::X4(_, _, ref mut a, ..)) => a,
|
||||
(2, MultiLocation::X5(_, _, ref mut a, ..)) => a,
|
||||
(2, MultiLocation::X6(_, _, ref mut a, ..)) => a,
|
||||
(2, MultiLocation::X7(_, _, ref mut a, ..)) => a,
|
||||
(2, MultiLocation::X8(_, _, ref mut a, ..)) => a,
|
||||
(3, MultiLocation::X4(_, _, _, ref mut a)) => a,
|
||||
(3, MultiLocation::X5(_, _, _, ref mut a, ..)) => a,
|
||||
(3, MultiLocation::X6(_, _, _, ref mut a, ..)) => a,
|
||||
(3, MultiLocation::X7(_, _, _, ref mut a, ..)) => a,
|
||||
(3, MultiLocation::X8(_, _, _, ref mut a, ..)) => a,
|
||||
(4, MultiLocation::X5(_, _, _, _, ref mut a)) => a,
|
||||
(4, MultiLocation::X6(_, _, _, _, ref mut a, ..)) => a,
|
||||
(4, MultiLocation::X7(_, _, _, _, ref mut a, ..)) => a,
|
||||
(4, MultiLocation::X8(_, _, _, _, ref mut a, ..)) => a,
|
||||
(5, MultiLocation::X6(_, _, _, _, _, ref mut a)) => a,
|
||||
(5, MultiLocation::X7(_, _, _, _, _, ref mut a, ..)) => a,
|
||||
(5, MultiLocation::X8(_, _, _, _, _, ref mut a, ..)) => a,
|
||||
(6, MultiLocation::X7(_, _, _, _, _, _, ref mut a)) => a,
|
||||
(6, MultiLocation::X8(_, _, _, _, _, _, ref mut a, ..)) => a,
|
||||
(7, MultiLocation::X8(_, _, _, _, _, _, _, ref mut a)) => a,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -334,12 +466,71 @@ impl MultiLocation {
|
||||
/// Returns the number of `Parent` junctions at the beginning of `self`.
|
||||
pub fn parent_count(&self) -> usize {
|
||||
match self {
|
||||
MultiLocation::X8(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent, Junction::Parent, Junction::Parent
|
||||
) => 8,
|
||||
|
||||
MultiLocation::X8(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent, Junction::Parent, ..
|
||||
) => 7,
|
||||
MultiLocation::X7(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent, Junction::Parent
|
||||
) => 7,
|
||||
|
||||
MultiLocation::X8(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent, ..
|
||||
) => 6,
|
||||
MultiLocation::X7(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent, ..
|
||||
) => 6,
|
||||
MultiLocation::X6(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent,
|
||||
Junction::Parent
|
||||
) => 6,
|
||||
|
||||
MultiLocation::X8(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..
|
||||
) => 5,
|
||||
MultiLocation::X7(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..
|
||||
) => 5,
|
||||
MultiLocation::X6(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..
|
||||
) => 5,
|
||||
MultiLocation::X5(
|
||||
Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent
|
||||
) => 5,
|
||||
|
||||
MultiLocation::X8(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..) => 4,
|
||||
MultiLocation::X7(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..) => 4,
|
||||
MultiLocation::X6(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..) => 4,
|
||||
MultiLocation::X5(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent, ..) => 4,
|
||||
MultiLocation::X4(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent) => 4,
|
||||
|
||||
MultiLocation::X8(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||
MultiLocation::X7(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||
MultiLocation::X6(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||
MultiLocation::X5(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||
MultiLocation::X4(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||
MultiLocation::X3(Junction::Parent, Junction::Parent, Junction::Parent) => 3,
|
||||
|
||||
MultiLocation::X8(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X7(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X6(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X5(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X4(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X3(Junction::Parent, Junction::Parent, ..) => 2,
|
||||
MultiLocation::X2(Junction::Parent, Junction::Parent) => 2,
|
||||
|
||||
MultiLocation::X8(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X7(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X6(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X5(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X4(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X3(Junction::Parent, ..) => 1,
|
||||
MultiLocation::X2(Junction::Parent, ..) => 1,
|
||||
|
||||
@@ -6,6 +6,7 @@ description = "Tools & types for building with XCM and its executor."
|
||||
version = "0.8.30"
|
||||
|
||||
[dependencies]
|
||||
impl-trait-for-tuples = "0.2.0"
|
||||
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }
|
||||
xcm = { path = "..", default-features = false }
|
||||
xcm-executor = { path = "../xcm-executor", default-features = false }
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use sp_std::{result, convert::TryInto, marker::PhantomData};
|
||||
use xcm::v0::{Error as XcmError, Result, MultiAsset, MultiLocation};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
use frame_support::traits::{ExistenceRequirement::AllowDeath, WithdrawReasons};
|
||||
use xcm_executor::traits::{MatchesFungible, LocationConversion, TransactAsset};
|
||||
|
||||
@@ -24,7 +24,7 @@ use xcm_executor::traits::{MatchesFungible, LocationConversion, TransactAsset};
|
||||
enum Error {
|
||||
/// Asset not found.
|
||||
AssetNotFound,
|
||||
/// `MultiLocation` to `AccountId` Conversion failed.
|
||||
/// `MultiLocation` to `AccountId` conversion failed.
|
||||
AccountIdConversionFailed,
|
||||
/// `u128` amount to currency `Balance` conversion failed.
|
||||
AmountToBalanceConversionFailed,
|
||||
@@ -43,10 +43,7 @@ impl From<Error> for XcmError {
|
||||
}
|
||||
|
||||
pub struct CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId>(
|
||||
PhantomData<Currency>,
|
||||
PhantomData<Matcher>,
|
||||
PhantomData<AccountIdConverter>,
|
||||
PhantomData<AccountId>,
|
||||
PhantomData<(Currency, Matcher, AccountIdConverter, AccountId)>
|
||||
);
|
||||
|
||||
impl<
|
||||
@@ -59,13 +56,13 @@ impl<
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> Result {
|
||||
// Check we handle this asset.
|
||||
let amount: u128 = Matcher::matches_fungible(&what)
|
||||
.ok_or(XcmError::from(Error::AssetNotFound))?
|
||||
.ok_or(Error::AssetNotFound)?
|
||||
.saturated_into();
|
||||
let who = AccountIdConverter::from_location(who)
|
||||
.ok_or(XcmError::from(Error::AccountIdConversionFailed))?;
|
||||
.ok_or(Error::AccountIdConversionFailed)?;
|
||||
let balance_amount = amount
|
||||
.try_into()
|
||||
.map_err(|_| XcmError::from(Error::AmountToBalanceConversionFailed))?;
|
||||
.map_err(|_| Error::AmountToBalanceConversionFailed)?;
|
||||
let _imbalance = Currency::deposit_creating(&who, balance_amount);
|
||||
Ok(())
|
||||
}
|
||||
@@ -75,14 +72,14 @@ impl<
|
||||
who: &MultiLocation
|
||||
) -> result::Result<MultiAsset, XcmError> {
|
||||
// Check we handle this asset.
|
||||
let amount: u128 = Matcher::matches_fungible(&what)
|
||||
.ok_or(XcmError::from(Error::AssetNotFound))?
|
||||
let amount: u128 = Matcher::matches_fungible(what)
|
||||
.ok_or(Error::AssetNotFound)?
|
||||
.saturated_into();
|
||||
let who = AccountIdConverter::from_location(who)
|
||||
.ok_or(XcmError::from(Error::AccountIdConversionFailed))?;
|
||||
.ok_or(Error::AccountIdConversionFailed)?;
|
||||
let balance_amount = amount
|
||||
.try_into()
|
||||
.map_err(|_| XcmError::from(Error::AmountToBalanceConversionFailed))?;
|
||||
.map_err(|_| Error::AmountToBalanceConversionFailed)?;
|
||||
Currency::withdraw(&who, balance_amount, WithdrawReasons::TRANSFER, AllowDeath)
|
||||
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
|
||||
Ok(what.clone())
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use sp_std::{prelude::*, result, convert::TryFrom, marker::PhantomData, borrow::Borrow};
|
||||
use xcm::v0::{Error as XcmError, Result, MultiAsset, MultiLocation, Junction};
|
||||
use frame_support::traits::{Get, tokens::fungibles::Mutate as Fungibles};
|
||||
use xcm_executor::traits::{LocationConversion, TransactAsset};
|
||||
|
||||
/// Asset transaction errors.
|
||||
pub enum Error {
|
||||
/// Asset not found.
|
||||
AssetNotFound,
|
||||
/// `MultiLocation` to `AccountId` conversion failed.
|
||||
AccountIdConversionFailed,
|
||||
/// `u128` amount to currency `Balance` conversion failed.
|
||||
AmountToBalanceConversionFailed,
|
||||
/// `MultiLocation` to `AssetId` conversion failed.
|
||||
AssetIdConversionFailed,
|
||||
}
|
||||
|
||||
impl From<Error> for XcmError {
|
||||
fn from(e: Error) -> Self {
|
||||
match e {
|
||||
Error::AssetNotFound => XcmError::FailedToTransactAsset("AssetNotFound"),
|
||||
Error::AccountIdConversionFailed =>
|
||||
XcmError::FailedToTransactAsset("AccountIdConversionFailed"),
|
||||
Error::AmountToBalanceConversionFailed =>
|
||||
XcmError::FailedToTransactAsset("AmountToBalanceConversionFailed"),
|
||||
Error::AssetIdConversionFailed =>
|
||||
XcmError::FailedToTransactAsset("AssetIdConversionFailed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic third-party conversion trait. Use this when you don't want to force the user to use default
|
||||
/// impls of `From` and `Into` for the types you wish to convert between.
|
||||
///
|
||||
/// One of `convert`/`convert_ref` and `reverse`/`reverse_ref` MUST be implemented. If possible, implement
|
||||
/// `convert_ref`, since this will never result in a clone. Use `convert` when you definitely need to consume
|
||||
/// the source value.
|
||||
pub trait Convert<A: Clone, B: Clone> {
|
||||
/// Convert from `value` (of type `A`) into an equivalent value of type `B`, `Err` if not possible.
|
||||
fn convert(value: A) -> result::Result<B, A> { Self::convert_ref(&value).map_err(|_| value) }
|
||||
fn convert_ref(value: impl Borrow<A>) -> result::Result<B, ()> {
|
||||
Self::convert(value.borrow().clone()).map_err(|_| ())
|
||||
}
|
||||
/// Convert from `value` (of type `B`) into an equivalent value of type `A`, `Err` if not possible.
|
||||
fn reverse(value: B) -> result::Result<A, B> { Self::reverse_ref(&value).map_err(|_| value) }
|
||||
fn reverse_ref(value: impl Borrow<B>) -> result::Result<A, ()> {
|
||||
Self::reverse(value.borrow().clone()).map_err(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl<A: Clone, B: Clone> Convert<A, B> for Tuple {
|
||||
fn convert(value: A) -> result::Result<B, A> {
|
||||
for_tuples!( #(
|
||||
let value = match Tuple::convert(value) {
|
||||
Ok(result) => return Ok(result),
|
||||
Err(v) => v,
|
||||
};
|
||||
)* );
|
||||
Err(value)
|
||||
}
|
||||
fn reverse(value: B) -> result::Result<A, B> {
|
||||
for_tuples!( #(
|
||||
let value = match Tuple::reverse(value) {
|
||||
Ok(result) => return Ok(result),
|
||||
Err(v) => v,
|
||||
};
|
||||
)* );
|
||||
Err(value)
|
||||
}
|
||||
fn convert_ref(value: impl Borrow<A>) -> result::Result<B, ()> {
|
||||
let value = value.borrow();
|
||||
for_tuples!( #(
|
||||
match Tuple::convert_ref(value) {
|
||||
Ok(result) => return Ok(result),
|
||||
Err(_) => (),
|
||||
}
|
||||
)* );
|
||||
Err(())
|
||||
}
|
||||
fn reverse_ref(value: impl Borrow<B>) -> result::Result<A, ()> {
|
||||
let value = value.borrow();
|
||||
for_tuples!( #(
|
||||
match Tuple::reverse_ref(value.clone()) {
|
||||
Ok(result) => return Ok(result),
|
||||
Err(_) => (),
|
||||
}
|
||||
)* );
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple pass-through which implements `BytesConversion` while not doing any conversion.
|
||||
pub struct Identity;
|
||||
impl<T: Clone> Convert<T, T> for Identity {
|
||||
fn convert(value: T) -> result::Result<T, T> { Ok(value) }
|
||||
fn reverse(value: T) -> result::Result<T, T> { Ok(value) }
|
||||
}
|
||||
|
||||
/// Implementation of `Convert` trait using `TryFrom`.
|
||||
pub struct JustTry;
|
||||
impl<Source: TryFrom<Dest> + Clone, Dest: TryFrom<Source> + Clone> Convert<Source, Dest> for JustTry {
|
||||
fn convert(value: Source) -> result::Result<Dest, Source> {
|
||||
Dest::try_from(value.clone()).map_err(|_| value)
|
||||
}
|
||||
fn reverse(value: Dest) -> result::Result<Source, Dest> {
|
||||
Source::try_from(value.clone()).map_err(|_| value)
|
||||
}
|
||||
}
|
||||
|
||||
use parity_scale_codec::{Encode, Decode};
|
||||
/// Implementation of `Convert<_, Vec<u8>>` using the parity scale codec.
|
||||
pub struct Encoded;
|
||||
impl<T: Clone + Encode + Decode> Convert<T, Vec<u8>> for Encoded {
|
||||
fn convert_ref(value: impl Borrow<T>) -> result::Result<Vec<u8>, ()> { Ok(value.borrow().encode()) }
|
||||
fn reverse_ref(bytes: impl Borrow<Vec<u8>>) -> result::Result<T, ()> {
|
||||
T::decode(&mut &bytes.borrow()[..]).map_err(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Convert<Vec<u8>, _>` using the parity scale codec.
|
||||
pub struct Decoded;
|
||||
impl<T: Clone + Encode + Decode> Convert<Vec<u8>, T> for Decoded {
|
||||
fn convert_ref(bytes: impl Borrow<Vec<u8>>) -> result::Result<T, ()> {
|
||||
T::decode(&mut &bytes.borrow()[..]).map_err(|_| ())
|
||||
}
|
||||
fn reverse_ref(value: impl Borrow<T>) -> result::Result<Vec<u8>, ()> { Ok(value.borrow().encode()) }
|
||||
}
|
||||
|
||||
/// Converter struct implementing `AssetIdConversion` converting a numeric asset ID (must be TryFrom/TryInto<u128>)
|
||||
/// into a `GeneralIndex` junction, prefixed by some `MultiLocation` value. The `MultiLocation` value will
|
||||
/// typically be a `PalletInstance` junction.
|
||||
pub struct AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId>(PhantomData<(Prefix, AssetId, ConvertAssetId)>);
|
||||
impl<
|
||||
Prefix: Get<MultiLocation>,
|
||||
AssetId: Clone,
|
||||
ConvertAssetId: Convert<u128, AssetId>,
|
||||
> Convert<MultiLocation, AssetId> for AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId> {
|
||||
fn convert_ref(id: impl Borrow<MultiLocation>) -> result::Result<AssetId, ()> {
|
||||
let prefix = Prefix::get();
|
||||
let id = id.borrow();
|
||||
if !prefix.iter().enumerate().all(|(index, item)| id.at(index) == Some(item)) {
|
||||
return Err(())
|
||||
}
|
||||
match id.at(prefix.len()) {
|
||||
Some(Junction::GeneralIndex { id }) => ConvertAssetId::convert_ref(id),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
fn reverse_ref(what: impl Borrow<AssetId>) -> result::Result<MultiLocation, ()> {
|
||||
let mut location = Prefix::get();
|
||||
let id = ConvertAssetId::reverse_ref(what)?;
|
||||
location.push(Junction::GeneralIndex { id }).map_err(|_| ())?;
|
||||
Ok(location)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MatchesFungibles<AssetId, Balance> {
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
> MatchesFungibles<AssetId, Balance> for Tuple {
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
|
||||
for_tuples!( #(
|
||||
match Tuple::matches_fungibles(a) { o @ Ok(_) => return o, _ => () }
|
||||
)* );
|
||||
Err(Error::AssetNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertedConcreteAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>(
|
||||
PhantomData<(AssetId, Balance, ConvertAssetId, ConvertBalance)>
|
||||
);
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
ConvertAssetId: Convert<MultiLocation, AssetId>,
|
||||
ConvertBalance: Convert<u128, Balance>,
|
||||
> MatchesFungibles<AssetId, Balance> for
|
||||
ConvertedConcreteAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
|
||||
let (id, amount) = match a {
|
||||
MultiAsset::ConcreteFungible { id, amount } => (id, amount),
|
||||
_ => return Err(Error::AssetNotFound),
|
||||
};
|
||||
let what = ConvertAssetId::convert_ref(id).map_err(|_| Error::AssetIdConversionFailed)?;
|
||||
let amount = ConvertBalance::convert_ref(amount).map_err(|_| Error::AmountToBalanceConversionFailed)?;
|
||||
Ok((what, amount))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertedAbstractAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>(
|
||||
PhantomData<(AssetId, Balance, ConvertAssetId, ConvertBalance)>
|
||||
);
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
ConvertAssetId: Convert<Vec<u8>, AssetId>,
|
||||
ConvertBalance: Convert<u128, Balance>,
|
||||
> MatchesFungibles<AssetId, Balance> for
|
||||
ConvertedAbstractAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
|
||||
let (id, amount) = match a {
|
||||
MultiAsset::AbstractFungible { id, amount } => (id, amount),
|
||||
_ => return Err(Error::AssetNotFound),
|
||||
};
|
||||
let what = ConvertAssetId::convert_ref(id).map_err(|_| Error::AssetIdConversionFailed)?;
|
||||
let amount = ConvertBalance::convert_ref(amount).map_err(|_| Error::AmountToBalanceConversionFailed)?;
|
||||
Ok((what, amount))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId>(
|
||||
PhantomData<(Assets, Matcher, AccountIdConverter, AccountId)>
|
||||
);
|
||||
|
||||
impl<
|
||||
Assets: Fungibles<AccountId>,
|
||||
Matcher: MatchesFungibles<Assets::AssetId, Assets::Balance>,
|
||||
AccountIdConverter: LocationConversion<AccountId>,
|
||||
AccountId, // can't get away without it since Currency is generic over it.
|
||||
> TransactAsset for FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId> {
|
||||
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> Result {
|
||||
// Check we handle this asset.
|
||||
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
|
||||
let who = AccountIdConverter::from_location(who)
|
||||
.ok_or(Error::AccountIdConversionFailed)?;
|
||||
Assets::deposit(asset_id, &who, amount)
|
||||
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation
|
||||
) -> result::Result<MultiAsset, XcmError> {
|
||||
// Check we handle this asset.
|
||||
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
|
||||
let who = AccountIdConverter::from_location(who)
|
||||
.ok_or(Error::AccountIdConversionFailed)?;
|
||||
Assets::withdraw(asset_id, &who, amount)
|
||||
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
|
||||
Ok(what.clone())
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,9 @@ pub use origin_conversion::{
|
||||
};
|
||||
|
||||
mod currency_adapter;
|
||||
mod fungibles_adapter;
|
||||
pub use currency_adapter::CurrencyAdapter;
|
||||
pub use fungibles_adapter::FungiblesAdapter;
|
||||
|
||||
use sp_std::marker::PhantomData;
|
||||
use xcm_executor::traits::InvertLocation;
|
||||
|
||||
@@ -117,15 +117,22 @@ impl<T: Get<&'static [u8]>, B: TryFrom<u128>> MatchesFungible<B> for IsAbstract<
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: impl for tuples
|
||||
impl<B: From<u128>, X: MatchesFungible<B>, Y: MatchesFungible<B>> MatchesFungible<B> for (X, Y) {
|
||||
fn matches_fungible(a: &MultiAsset) -> Option<B> {
|
||||
X::matches_fungible(a).or_else(|| Y::matches_fungible(a))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LocationConversion<AccountId> {
|
||||
fn from_location(location: &MultiLocation) -> Option<AccountId>;
|
||||
fn try_into_location(who: AccountId) -> Result<MultiLocation, AccountId>;
|
||||
// TODO: change to use Convert trait.
|
||||
/// Attempt to convert a location into some value of type `T`, or vice-versa.
|
||||
pub trait LocationConversion<T> {
|
||||
/// Convert `location` into `Some` value of `T`, or `None` if not possible.
|
||||
// TODO: consider returning Result<T, ()> instead.
|
||||
fn from_location(location: &MultiLocation) -> Option<T>;
|
||||
/// Convert some value `value` into a `location`, `Err`oring with the original `value` if not possible.
|
||||
// TODO: consider renaming `into_location`
|
||||
fn try_into_location(value: T) -> Result<MultiLocation, T>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
|
||||
Reference in New Issue
Block a user