Skip to content

Commit

Permalink
Runtime API implementation ok
Browse files Browse the repository at this point in the history
  • Loading branch information
ntn-x2 committed Oct 8, 2024
1 parent 2a4000e commit e3e1bb3
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 23 deletions.
37 changes: 19 additions & 18 deletions pallets/pallet-asset-switch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use frame_support::traits::{
PalletInfoAccess,
};
use parity_scale_codec::{Decode, Encode};
use sp_runtime::traits::{Get, TrailingZeroInput, Zero};
use sp_runtime::traits::{TrailingZeroInput, Zero};
use sp_std::boxed::Box;

pub use crate::pallet::*;
Expand Down Expand Up @@ -531,14 +531,24 @@ pub mod pallet {

// 7. Compose and validate XCM message
let query_id = T::QueryIdProvider::next_id();
let universal_location = T::UniversalLocation::get();
let our_location_for_destination = universal_location.invert_target(&destination_v4).map_err(|e| {
log::error!(
target: LOG_TARGET,
"Failed to invert universal location {:?} for destination {:?} with error {:?}",
universal_location, destination_v4, e
);
Error::<T, I>::Internal
})?;
let remote_xcm = Self::compute_xcm_for_switch(
&our_location_for_destination,
&submitter_as_location,
&beneficiary_v4,
remote_asset_amount_as_u128,
&asset_id_v4,
&remote_asset_fee_v4,
query_id,
)?;
);
let xcm_ticket =
validate_send::<T::XcmRouter>(destination_v4.clone(), remote_xcm.clone()).map_err(|e| {
log::info!(
Expand Down Expand Up @@ -758,26 +768,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
}

pub fn compute_xcm_for_switch(
inverted_universal_location: &Location,
from: &Location,
to: &Location,
amount: u128,
asset_id: &AssetId,
remote_asset_fee: &Asset,
query_id: QueryId,
) -> Result<Xcm<()>, Error<T, I>> {
let universal_location = T::UniversalLocation::get();
let our_location_for_destination = universal_location.invert_target(to).map_err(|e| {
log::error!(
target: LOG_TARGET,
"Failed to invert universal location {:?} for destination {:?} with error {:?}",
universal_location, to, e
);
Error::<T, I>::Internal
})?;
) -> Xcm<()> {
let appendix = vec![
ReportHolding {
response_info: QueryResponseInfo {
destination: our_location_for_destination.clone(),
destination: inverted_universal_location.clone(),
max_weight: Weight::zero(),
query_id,
},
Expand All @@ -795,7 +797,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
id: asset_id.clone(),
fun: WildFungibility::Fungible,
}),
beneficiary: our_location_for_destination,
beneficiary: inverted_universal_location.clone(),
},
RefundSurplus,
// Refund the XCM fee left to the user. We are purposefully only selecting the XCM fee asset, although
Expand Down Expand Up @@ -824,7 +826,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
// have full control of this balance)
// 5. Try to deposit the withdrawn asset into the user's account. This operation
// could fail and the error is handled in the appendix.
let remote_xcm: Xcm<()> = vec![
vec![
WithdrawAsset(remote_asset_fee.clone().into()),
BuyExecution {
weight_limit: WeightLimit::Unlimited,
Expand All @@ -841,11 +843,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
WithdrawAsset((asset_id.clone(), amount).into()),
DepositAsset {
assets: AssetFilter::Definite((asset_id.clone(), amount).into()),
beneficiary: from.clone(),
beneficiary: to.clone(),
},
]
.into();
Ok(remote_xcm)
.into()
}

// Read the first item in the storage and returns `true` if `Some`, and `false`
Expand Down
2 changes: 1 addition & 1 deletion runtime-api/asset-switch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ sp_api::decl_runtime_apis! {
Xcm: Codec,
{
fn pool_account_id(pair_id: Vec<u8>, asset_id: AssetId) -> Result<AccountId, Error>;
fn xcm_for_switch(pair_id: Vec<u8>, asset_id: AssetId, from: AccountId, to: Destination, amount: Amount) -> Result<Xcm, Error>;
fn xcm_for_switch(pair_id: Vec<u8>, from: AccountId, to: Destination, amount: Amount) -> Result<Xcm, Error>;
}
}
2 changes: 2 additions & 0 deletions runtimes/common/src/asset_switch/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ pub enum Error {
InvalidInput,
SwitchPoolNotFound,
Internal,
SwitchPoolNotSet,
Other(String),
}
40 changes: 38 additions & 2 deletions runtimes/peregrine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ use sp_runtime::{
};
use sp_std::{cmp::Ordering, prelude::*};
use sp_version::RuntimeVersion;
use xcm::{v4::Location, VersionedAssetId};
use xcm::{
v4::{opaque::Xcm, Location},
VersionedAssetId, VersionedLocation,
};
use xcm_builder::{FungiblesAdapter, NoChecking};

use delegation::DelegationAc;
Expand Down Expand Up @@ -1591,7 +1594,7 @@ impl_runtime_apis! {
}
}

impl pallet_asset_switch_runtime_api::AssetSwitch<Block, VersionedAssetId, AccountId, AssetSwitchApiError> for Runtime {
impl pallet_asset_switch_runtime_api::AssetSwitch<Block, VersionedAssetId, AccountId, u128, VersionedLocation, AssetSwitchApiError, Xcm> for Runtime {
fn pool_account_id(pair_id: Vec<u8>, asset_id: VersionedAssetId) -> Result<AccountId, AssetSwitchApiError> {
use core::str;
use frame_support::traits::PalletInfoAccess;
Expand All @@ -1609,6 +1612,39 @@ impl_runtime_apis! {
_ => Err(AssetSwitchApiError::SwitchPoolNotFound)
}
}

fn xcm_for_switch(pair_id: Vec<u8>, from: AccountId, to: VersionedLocation, amount: u128) -> Result<Xcm, AssetSwitchApiError> {
use core::str;
use frame_support::traits::PalletInfoAccess;
use sp_runtime::traits::TryConvert;
use xcm::v4::{AssetId, Asset};

use pallet_asset_switch::traits::QueryIdProvider;

let Ok(pair_id_as_string) = str::from_utf8(pair_id.as_slice()) else {
return Err(AssetSwitchApiError::InvalidInput);
};

if pair_id_as_string != AssetSwitchPool1::name() {
return Err(AssetSwitchApiError::SwitchPoolNotFound);
}

let Some(switch_pair) = AssetSwitchPool1::switch_pair() else {
return Err(AssetSwitchApiError::SwitchPoolNotSet);
};

let from_v4 = AccountId32ToAccountId32JunctionConverter::try_convert(from).map_err(|e| AssetSwitchApiError::Other(e.to_string()))?;
let to_v4 = Location::try_from(to.clone()).map_err(|_| AssetSwitchApiError::Other(format!("Failed to convert provided location {:?} to a `v4` variant.", to)))?;
let our_location_for_destination = {
let universal_location = UniversalLocation::get();
universal_location.invert_target(&to_v4)
}.map_err(|_| AssetSwitchApiError::Other(format!("Failed to invert target for target destination {:?}", to)))?;
let asset_id_v4 = AssetId::try_from(switch_pair.remote_asset_id).map_err(|_| AssetSwitchApiError::Internal)?;
let remote_asset_fee_v4 = Asset::try_from(switch_pair.remote_xcm_fee).map_err(|_| AssetSwitchApiError::Internal)?;
let query_id = QueryIdProviderViaXcmPallet::<Runtime>::next_id();

Ok(AssetSwitchPool1::compute_xcm_for_switch(&our_location_for_destination, &from_v4.into(), &to_v4, amount, &asset_id_v4, &remote_asset_fee_v4, query_id))
}
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down
40 changes: 38 additions & 2 deletions runtimes/spiritnet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ use sp_runtime::{
};
use sp_std::{cmp::Ordering, prelude::*};
use sp_version::RuntimeVersion;
use xcm::{v4::Location, VersionedAssetId};
use xcm::{
v4::{opaque::Xcm, Location},
VersionedAssetId, VersionedLocation,
};
use xcm_builder::{FungiblesAdapter, NoChecking};

use delegation::DelegationAc;
Expand Down Expand Up @@ -1581,7 +1584,7 @@ impl_runtime_apis! {
}
}

impl pallet_asset_switch_runtime_api::AssetSwitch<Block, VersionedAssetId, AccountId, AssetSwitchApiError> for Runtime {
impl pallet_asset_switch_runtime_api::AssetSwitch<Block, VersionedAssetId, AccountId, u128, VersionedLocation, AssetSwitchApiError, Xcm> for Runtime {
fn pool_account_id(pair_id: Vec<u8>, asset_id: VersionedAssetId) -> Result<AccountId, AssetSwitchApiError> {
use core::str;
use frame_support::traits::PalletInfoAccess;
Expand All @@ -1599,6 +1602,39 @@ impl_runtime_apis! {
_ => Err(AssetSwitchApiError::SwitchPoolNotFound)
}
}

fn xcm_for_switch(pair_id: Vec<u8>, from: AccountId, to: VersionedLocation, amount: u128) -> Result<Xcm, AssetSwitchApiError> {
use core::str;
use frame_support::traits::PalletInfoAccess;
use sp_runtime::traits::TryConvert;
use xcm::v4::{AssetId, Asset};

use pallet_asset_switch::traits::QueryIdProvider;

let Ok(pair_id_as_string) = str::from_utf8(pair_id.as_slice()) else {
return Err(AssetSwitchApiError::InvalidInput);
};

if pair_id_as_string != AssetSwitchPool1::name() {
return Err(AssetSwitchApiError::SwitchPoolNotFound);
}

let Some(switch_pair) = AssetSwitchPool1::switch_pair() else {
return Err(AssetSwitchApiError::SwitchPoolNotSet);
};

let from_v4 = AccountId32ToAccountId32JunctionConverter::try_convert(from).map_err(|e| AssetSwitchApiError::Other(e.to_string()))?;
let to_v4 = Location::try_from(to.clone()).map_err(|_| AssetSwitchApiError::Other(format!("Failed to convert provided location {:?} to a `v4` variant.", to)))?;
let our_location_for_destination = {
let universal_location = UniversalLocation::get();
universal_location.invert_target(&to_v4)
}.map_err(|_| AssetSwitchApiError::Other(format!("Failed to invert target for target destination {:?}", to)))?;
let asset_id_v4 = AssetId::try_from(switch_pair.remote_asset_id).map_err(|_| AssetSwitchApiError::Internal)?;
let remote_asset_fee_v4 = Asset::try_from(switch_pair.remote_xcm_fee).map_err(|_| AssetSwitchApiError::Internal)?;
let query_id = QueryIdProviderViaXcmPallet::<Runtime>::next_id();

Ok(AssetSwitchPool1::compute_xcm_for_switch(&our_location_for_destination, &from_v4.into(), &to_v4, amount, &asset_id_v4, &remote_asset_fee_v4, query_id))
}
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down

0 comments on commit e3e1bb3

Please sign in to comment.