Skip to content

Commit

Permalink
Add XcmPaymentApi to all runtimes (#592)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmpolaczyk authored Jun 24, 2024
1 parent 77296a6 commit 395df84
Show file tree
Hide file tree
Showing 10 changed files with 408 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Mark typescript-api folder as auto generated
typescript-api/** linguist-generated=true
typescript-api/package.json linguist-generated=false
typescript-api/scripts/** linguist-generated=false
typescript-api/src/*/interfaces/tanssi/definitions.ts linguist-generated=false
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ staging-xcm-builder = { git = "https://github.com/moondance-labs/polkadot-sdk",
staging-xcm-executor = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.11.0", default-features = false }
westend-runtime = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.11.0", default-features = false }
westend-runtime-constants = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.11.0", default-features = false }
xcm-fee-payment-runtime-api = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.11.0", default-features = false }

# Polkadot (client)
polkadot-cli = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.11.0" }
Expand Down
2 changes: 2 additions & 0 deletions container-chains/runtime-templates/frontier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ polkadot-runtime-common = { workspace = true }
staging-xcm = { workspace = true }
staging-xcm-builder = { workspace = true }
staging-xcm-executor = { workspace = true }
xcm-fee-payment-runtime-api = { workspace = true }

# Cumulus
cumulus-pallet-dmp-queue = { workspace = true }
Expand Down Expand Up @@ -226,6 +227,7 @@ std = [
"staging-xcm-executor/std",
"staging-xcm/std",
"tanssi-runtime-common/std",
"xcm-fee-payment-runtime-api/std",
"xcm-primitives/std",
]

Expand Down
69 changes: 65 additions & 4 deletions container-chains/runtime-templates/frontier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,17 @@ use {
pallet_prelude::DispatchResult,
parameter_types,
traits::{
ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, Currency as CurrencyT,
FindAuthor, Imbalance, InsideBoth, InstanceFilter, OnFinalize, OnUnbalanced,
tokens::ConversionToAssetBalance, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8,
Contains, Currency as CurrencyT, FindAuthor, Imbalance, InsideBoth, InstanceFilter,
OnFinalize, OnUnbalanced,
},
weights::{
constants::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
WEIGHT_REF_TIME_PER_SECOND,
},
ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
ConstantMultiplier, Weight, WeightToFee as _, WeightToFeeCoefficient,
WeightToFeeCoefficients, WeightToFeePolynomial,
},
},
frame_system::{
Expand Down Expand Up @@ -93,6 +94,10 @@ use {
},
sp_std::prelude::*,
sp_version::RuntimeVersion,
staging_xcm::{
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
},
xcm_fee_payment_runtime_api::Error as XcmPaymentApiError,
};
pub use {
sp_consensus_aura::sr25519::AuthorityId as AuraId,
Expand Down Expand Up @@ -1648,6 +1653,62 @@ impl_runtime_apis! {
SLOT_DURATION
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: staging_xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, 3 | 4) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

Ok([VersionedAssetId::V4(xcm_config::SelfReserve::get().into())]
.into_iter()
.chain(
pallet_asset_rate::ConversionRateToNative::<Runtime>::iter_keys().filter_map(|asset_id_u16| {
pallet_foreign_asset_creator::AssetIdToForeignAsset::<Runtime>::get(asset_id_u16).map(|location| {
VersionedAssetId::V4(location.into())
}).or_else(|| {
log::warn!("Asset `{}` is present in pallet_asset_rate but not in pallet_foreign_asset_creator", asset_id_u16);
None
})
})
)
.filter_map(|asset| asset.into_version(xcm_version).map_err(|e| {
log::warn!("Failed to convert asset to version {}: {:?}", xcm_version, e);
}).ok())
.collect())
}

fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let local_asset = VersionedAssetId::V4(xcm_config::SelfReserve::get().into());
let asset = asset
.into_version(4)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if asset == local_asset {
Ok(WeightToFee::weight_to_fee(&weight))
} else {
let native_fee = WeightToFee::weight_to_fee(&weight);
let asset_v4: staging_xcm::opaque::lts::AssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let location: staging_xcm::opaque::lts::Location = asset_v4.0;
let asset_id = pallet_foreign_asset_creator::ForeignAssetToAssetId::<Runtime>::get(location).ok_or(XcmPaymentApiError::AssetNotFound)?;
let asset_rate = AssetRate::to_asset_balance(native_fee, asset_id);
match asset_rate {
Ok(x) => Ok(x),
Err(pallet_asset_rate::Error::UnknownAssetKind) => Err(XcmPaymentApiError::AssetNotFound),
// Error when converting native balance to asset balance, probably overflow
Err(_e) => Err(XcmPaymentApiError::WeightNotComputable),
}
}
}

fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
}

#[allow(dead_code)]
Expand Down
2 changes: 2 additions & 0 deletions container-chains/runtime-templates/simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ polkadot-runtime-common = { workspace = true }
staging-xcm = { workspace = true }
staging-xcm-builder = { workspace = true }
staging-xcm-executor = { workspace = true }
xcm-fee-payment-runtime-api = { workspace = true }

# Cumulus
cumulus-pallet-dmp-queue = { workspace = true }
Expand Down Expand Up @@ -180,6 +181,7 @@ std = [
"staging-xcm-executor/std",
"staging-xcm/std",
"tanssi-runtime-common/std",
"xcm-fee-payment-runtime-api/std",
"xcm-primitives/std",
]

Expand Down
67 changes: 64 additions & 3 deletions container-chains/runtime-templates/simple/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@ use {
pallet_prelude::DispatchResult,
parameter_types,
traits::{
ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, InsideBoth, InstanceFilter,
tokens::ConversionToAssetBalance, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8,
Contains, InsideBoth, InstanceFilter,
},
weights::{
constants::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
WEIGHT_REF_TIME_PER_SECOND,
},
ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
ConstantMultiplier, Weight, WeightToFee as _, WeightToFeeCoefficient,
WeightToFeeCoefficients, WeightToFeePolynomial,
},
},
frame_system::{
Expand All @@ -75,6 +76,10 @@ use {
},
sp_std::prelude::*,
sp_version::RuntimeVersion,
staging_xcm::{
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
},
xcm_fee_payment_runtime_api::Error as XcmPaymentApiError,
};

pub mod xcm_config;
Expand Down Expand Up @@ -1126,6 +1131,62 @@ impl_runtime_apis! {
SLOT_DURATION
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: staging_xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, 3 | 4) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

Ok([VersionedAssetId::V4(xcm_config::SelfReserve::get().into())]
.into_iter()
.chain(
pallet_asset_rate::ConversionRateToNative::<Runtime>::iter_keys().filter_map(|asset_id_u16| {
pallet_foreign_asset_creator::AssetIdToForeignAsset::<Runtime>::get(asset_id_u16).map(|location| {
VersionedAssetId::V4(location.into())
}).or_else(|| {
log::warn!("Asset `{}` is present in pallet_asset_rate but not in pallet_foreign_asset_creator", asset_id_u16);
None
})
})
)
.filter_map(|asset| asset.into_version(xcm_version).map_err(|e| {
log::warn!("Failed to convert asset to version {}: {:?}", xcm_version, e);
}).ok())
.collect())
}

fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let local_asset = VersionedAssetId::V4(xcm_config::SelfReserve::get().into());
let asset = asset
.into_version(4)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if asset == local_asset {
Ok(WeightToFee::weight_to_fee(&weight))
} else {
let native_fee = WeightToFee::weight_to_fee(&weight);
let asset_v4: staging_xcm::opaque::lts::AssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let location: staging_xcm::opaque::lts::Location = asset_v4.0;
let asset_id = pallet_foreign_asset_creator::ForeignAssetToAssetId::<Runtime>::get(location).ok_or(XcmPaymentApiError::AssetNotFound)?;
let asset_rate = AssetRate::to_asset_balance(native_fee, asset_id);
match asset_rate {
Ok(x) => Ok(x),
Err(pallet_asset_rate::Error::UnknownAssetKind) => Err(XcmPaymentApiError::AssetNotFound),
// Error when converting native balance to asset balance, probably overflow
Err(_e) => Err(XcmPaymentApiError::WeightNotComputable),
}
}
}

fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
}

#[allow(dead_code)]
Expand Down
2 changes: 2 additions & 0 deletions runtime/dancebox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ polkadot-runtime-common = { workspace = true }
staging-xcm = { workspace = true }
staging-xcm-builder = { workspace = true }
staging-xcm-executor = { workspace = true }
xcm-fee-payment-runtime-api = { workspace = true }

# Cumulus
cumulus-pallet-dmp-queue = { workspace = true }
Expand Down Expand Up @@ -270,6 +271,7 @@ std = [
"tp-traits/std",
"westend-runtime-constants/std",
"westend-runtime/std",
"xcm-fee-payment-runtime-api/std",
"xcm-primitives/std",
]

Expand Down
68 changes: 64 additions & 4 deletions runtime/dancebox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ use {
traits::{
fungible::{Balanced, Credit, Inspect, InspectHold, Mutate, MutateHold},
tokens::{
imbalance::ResolveTo, PayFromAccount, Precision, Preservation,
UnityAssetBalanceConversion,
imbalance::ResolveTo, ConversionToAssetBalance, PayFromAccount, Precision,
Preservation, UnityAssetBalanceConversion,
},
ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse,
Imbalance, InsideBoth, InstanceFilter, OnUnbalanced, ValidatorRegistration,
Expand All @@ -62,8 +62,8 @@ use {
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
WEIGHT_REF_TIME_PER_SECOND,
},
ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
ConstantMultiplier, Weight, WeightToFee as _, WeightToFeeCoefficient,
WeightToFeeCoefficients, WeightToFeePolynomial,
},
PalletId,
},
Expand Down Expand Up @@ -102,10 +102,14 @@ use {
},
sp_std::{collections::btree_set::BTreeSet, marker::PhantomData, prelude::*},
sp_version::RuntimeVersion,
staging_xcm::{
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
},
tp_traits::{
GetContainerChainAuthor, GetHostConfiguration, GetSessionContainerChains,
RelayStorageRootProvider, RemoveInvulnerables, RemoveParaIdsWithNoCredits, SlotFrequency,
},
xcm_fee_payment_runtime_api::Error as XcmPaymentApiError,
};
pub use {
dp_core::{AccountId, Address, Balance, BlockNumber, Hash, Header, Index, Signature},
Expand Down Expand Up @@ -2607,6 +2611,62 @@ impl_runtime_apis! {
XcmCoreBuyer::is_core_buying_allowed(para_id)
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: staging_xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, 3 | 4) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

Ok([VersionedAssetId::V4(xcm_config::SelfReserve::get().into())]
.into_iter()
.chain(
pallet_asset_rate::ConversionRateToNative::<Runtime>::iter_keys().filter_map(|asset_id_u16| {
pallet_foreign_asset_creator::AssetIdToForeignAsset::<Runtime>::get(asset_id_u16).map(|location| {
VersionedAssetId::V4(location.into())
}).or_else(|| {
log::warn!("Asset `{}` is present in pallet_asset_rate but not in pallet_foreign_asset_creator", asset_id_u16);
None
})
})
)
.filter_map(|asset| asset.into_version(xcm_version).map_err(|e| {
log::warn!("Failed to convert asset to version {}: {:?}", xcm_version, e);
}).ok())
.collect())
}

fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let local_asset = VersionedAssetId::V4(xcm_config::SelfReserve::get().into());
let asset = asset
.into_version(4)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if asset == local_asset {
Ok(WeightToFee::weight_to_fee(&weight))
} else {
let native_fee = WeightToFee::weight_to_fee(&weight);
let asset_v4: staging_xcm::opaque::lts::AssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let location: staging_xcm::opaque::lts::Location = asset_v4.0;
let asset_id = pallet_foreign_asset_creator::ForeignAssetToAssetId::<Runtime>::get(location).ok_or(XcmPaymentApiError::AssetNotFound)?;
let asset_rate = AssetRate::to_asset_balance(native_fee, asset_id);
match asset_rate {
Ok(x) => Ok(x),
Err(pallet_asset_rate::Error::UnknownAssetKind) => Err(XcmPaymentApiError::AssetNotFound),
// Error when converting native balance to asset balance, probably overflow
Err(_e) => Err(XcmPaymentApiError::WeightNotComputable),
}
}
}

fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
}

#[allow(dead_code)]
Expand Down
Loading

0 comments on commit 395df84

Please sign in to comment.