Skip to content

Commit

Permalink
XcmPaymentApi refactored, DryRunApi implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
ipapandinas committed Sep 10, 2024
1 parent b6506cc commit 6d63a79
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 115 deletions.
85 changes: 47 additions & 38 deletions runtime/astar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ use sp_runtime::{
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use xcm::{
v4::{AssetId as XcmAssetId, Location as XcmLocation},
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
};
use xcm_fee_payment_runtime_api::{
dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
fees::Error as XcmPaymentApiError,
};
use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError;

use astar_primitives::{
dapp_staking::{
Expand Down Expand Up @@ -1907,52 +1910,48 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, xcm::v3::VERSION | xcm::v4::VERSION) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

// Native asset is always supported
let native_asset_location: XcmLocation = XcmLocation::try_from(xcm_config::AstarLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

Ok([VersionedAssetId::V4(native_asset_location.into())]
.into_iter()
// Acquire foreign assets which have 'units per second' configured
.chain(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(|asset_location| {

match XcmLocation::try_from(asset_location) {
Ok(asset) => Some(VersionedAssetId::V4(asset.into())),
Err(_) => None,
}
})
).filter_map(|asset| asset.into_version(xcm_version).ok()).collect())
let mut acceptable_assets = vec![XcmAssetId::from(xcm_config::AstarLocation::get())];

// Add foreign assets that have 'units per second' configured
acceptable_assets.extend(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(
|asset_location| match XcmLocation::try_from(asset_location) {
Ok(location) => Some(XcmAssetId::from(location)),
Err(_) => None,
},
),
);

PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
}

fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let native_asset_location = XcmLocation::try_from(xcm_config::AstarLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let native_asset = VersionedAssetId::V4(native_asset_location.into());

let asset = asset
.into_version(xcm::v4::VERSION)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if native_asset == asset {
Ok(XcmWeightToFee::weight_to_fee(&weight))
} else {
let asset_id: XcmAssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let versioned_location = VersionedLocation::V4(asset_id.0);

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
}
None => Err(XcmPaymentApiError::AssetNotFound),
match asset.try_as::<XcmAssetId>() {
// for native token
Ok(asset_id) if asset_id.0 == xcm_config::AstarLocation::get() => {
Ok(WeightToFee::weight_to_fee(&weight))
}
// for foreign assets that have 'units per second' configured
Ok(asset_id) => {
let versioned_location = VersionedLocation::V4(asset_id.0.clone());

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
},
None => Err(XcmPaymentApiError::AssetNotFound),
}
},
// for failed asset conversion
Err(_) => Err(XcmPaymentApiError::VersionedConversionFailed)
}
}

Expand All @@ -1965,6 +1964,16 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
fn dry_run_call(origin: OriginCaller, call: RuntimeCall) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call)
}

fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
}
}

impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {

fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
Expand Down
86 changes: 47 additions & 39 deletions runtime/shibuya/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,12 @@ use sp_runtime::{
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use xcm::{
v4::{AssetId as XcmAssetId, Location as XcmLocation},
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
};
use xcm_fee_payment_runtime_api::{
dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
fees::Error as XcmPaymentApiError,
};
use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError;

use astar_primitives::{
dapp_staking::{
Expand Down Expand Up @@ -2238,53 +2241,48 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, xcm::v3::VERSION | xcm::v4::VERSION) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

// Native asset is always supported
let native_asset_location: XcmLocation = XcmLocation::try_from(xcm_config::ShibuyaLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

Ok([VersionedAssetId::V4(native_asset_location.into())]
.into_iter()
// Acquire foreign assets which have 'units per second' configured
.chain(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(|asset_location| {

match XcmLocation::try_from(asset_location) {
Ok(asset) => Some(VersionedAssetId::V4(asset.into())),
Err(_) => None,
}
})
).filter_map(|asset| asset.into_version(xcm_version).ok()).collect())
let mut acceptable_assets = vec![XcmAssetId::from(xcm_config::ShibuyaLocation::get())];

// Add foreign assets that have 'units per second' configured
acceptable_assets.extend(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(
|asset_location| match XcmLocation::try_from(asset_location) {
Ok(location) => Some(XcmAssetId::from(location)),
Err(_) => None,
},
),
);

PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
}

// TODO: improve this function, reduce code duplication, especially on a such a functional level
fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let native_asset_location = XcmLocation::try_from(xcm_config::ShibuyaLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let native_asset = VersionedAssetId::V4(native_asset_location.into());

let asset = asset
.into_version(xcm::v4::VERSION)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if native_asset == asset {
Ok(XcmWeightToFee::weight_to_fee(&weight))
} else {
let asset_id: XcmAssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let versioned_location = VersionedLocation::V4(asset_id.0);

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
}
None => Err(XcmPaymentApiError::AssetNotFound),
match asset.try_as::<XcmAssetId>() {
// for native token
Ok(asset_id) if asset_id.0 == xcm_config::ShibuyaLocation::get() => {
Ok(WeightToFee::weight_to_fee(&weight))
}
// for foreign assets that have 'units per second' configured
Ok(asset_id) => {
let versioned_location = VersionedLocation::V4(asset_id.0.clone());

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
},
None => Err(XcmPaymentApiError::AssetNotFound),
}
},
// for failed asset conversion
Err(_) => Err(XcmPaymentApiError::VersionedConversionFailed)
}
}

Expand All @@ -2297,6 +2295,16 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
fn dry_run_call(origin: OriginCaller, call: RuntimeCall) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call)
}

fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
}
}

impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {

fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
Expand Down
85 changes: 47 additions & 38 deletions runtime/shiden/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ use sp_runtime::{
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use xcm::{
v4::{AssetId as XcmAssetId, Location as XcmLocation},
IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
};
use xcm_fee_payment_runtime_api::{
dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
fees::Error as XcmPaymentApiError,
};
use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError;

use astar_primitives::{
dapp_staking::{
Expand Down Expand Up @@ -1908,52 +1911,48 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::XcmPaymentApi<Block> for Runtime {
impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi<Block> for Runtime {
fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
if !matches!(xcm_version, xcm::v3::VERSION | xcm::v4::VERSION) {
return Err(XcmPaymentApiError::UnhandledXcmVersion);
}

// Native asset is always supported
let native_asset_location: XcmLocation = XcmLocation::try_from(xcm_config::ShidenLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

Ok([VersionedAssetId::V4(native_asset_location.into())]
.into_iter()
// Acquire foreign assets which have 'units per second' configured
.chain(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(|asset_location| {

match XcmLocation::try_from(asset_location) {
Ok(asset) => Some(VersionedAssetId::V4(asset.into())),
Err(_) => None,
}
})
).filter_map(|asset| asset.into_version(xcm_version).ok()).collect())
let mut acceptable_assets = vec![XcmAssetId::from(xcm_config::ShidenLocation::get())];

// Add foreign assets that have 'units per second' configured
acceptable_assets.extend(
pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(
|asset_location| match XcmLocation::try_from(asset_location) {
Ok(location) => Some(XcmAssetId::from(location)),
Err(_) => None,
},
),
);

PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
}

fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
let native_asset_location = XcmLocation::try_from(xcm_config::ShidenLocation::get())
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let native_asset = VersionedAssetId::V4(native_asset_location.into());

let asset = asset
.into_version(xcm::v4::VERSION)
.map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;

if native_asset == asset {
Ok(XcmWeightToFee::weight_to_fee(&weight))
} else {
let asset_id: XcmAssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
let versioned_location = VersionedLocation::V4(asset_id.0);

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
}
None => Err(XcmPaymentApiError::AssetNotFound),
match asset.try_as::<XcmAssetId>() {
// for native token
Ok(asset_id) if asset_id.0 == xcm_config::ShidenLocation::get() => {
Ok(WeightToFee::weight_to_fee(&weight))
}
// for foreign assets that have 'units per second' configured
Ok(asset_id) => {
let versioned_location = VersionedLocation::V4(asset_id.0.clone());

match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
Some(units_per_sec) => {
Ok(units_per_sec.saturating_mul(weight.ref_time() as u128)
/ (WEIGHT_REF_TIME_PER_SECOND as u128))
},
None => Err(XcmPaymentApiError::AssetNotFound),
}
},
// for failed asset conversion
Err(_) => Err(XcmPaymentApiError::VersionedConversionFailed)
}
}

Expand All @@ -1966,6 +1965,16 @@ impl_runtime_apis! {
}
}

impl xcm_fee_payment_runtime_api::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
fn dry_run_call(origin: OriginCaller, call: RuntimeCall) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call)
}

fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
}
}

impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {

fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
Expand Down

0 comments on commit 6d63a79

Please sign in to comment.