staging_xcm_builder/unique_instances/
adapter.rs1use core::marker::PhantomData;
18use frame_support::traits::tokens::asset_ops::{
19 common_strategies::{
20 ChangeOwnerFrom, ConfigValue, DeriveAndReportId, IfOwnedBy, Owner, WithConfig,
21 WithConfigValue,
22 },
23 AssetDefinition, Create, Restore, Stash, Update,
24};
25use xcm::latest::prelude::*;
26use xcm_executor::traits::{ConvertLocation, Error as MatchError, MatchesInstance, TransactAsset};
27
28use super::NonFungibleAsset;
29
30const LOG_TARGET: &str = "xcm::unique_instances";
31
32pub struct UniqueInstancesAdapter<AccountId, AccountIdConverter, Matcher, InstanceOps>(
45 PhantomData<(AccountId, AccountIdConverter, Matcher, InstanceOps)>,
46);
47
48impl<AccountId, AccountIdConverter, Matcher, InstanceOps> TransactAsset
49 for UniqueInstancesAdapter<AccountId, AccountIdConverter, Matcher, InstanceOps>
50where
51 AccountId: 'static,
52 AccountIdConverter: ConvertLocation<AccountId>,
53 Matcher: MatchesInstance<InstanceOps::Id>,
54 InstanceOps: AssetDefinition
55 + Restore<WithConfig<ConfigValue<Owner<AccountId>>>>
56 + Update<ChangeOwnerFrom<AccountId>>
57 + Stash<IfOwnedBy<AccountId>>,
58{
59 fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
60 tracing::trace!(
61 target: LOG_TARGET,
62 ?what,
63 ?who,
64 ?context,
65 "deposit_asset",
66 );
67
68 let instance_id = Matcher::matches_instance(what)?;
69 let who = AccountIdConverter::convert_location(who)
70 .ok_or(MatchError::AccountIdConversionFailed)?;
71
72 InstanceOps::restore(&instance_id, WithConfig::from(Owner::with_config_value(who)))
73 .map_err(|e| XcmError::FailedToTransactAsset(e.into()))
74 }
75
76 fn withdraw_asset(
77 what: &Asset,
78 who: &Location,
79 maybe_context: Option<&XcmContext>,
80 ) -> Result<xcm_executor::AssetsInHolding, XcmError> {
81 tracing::trace!(
82 target: LOG_TARGET,
83 ?what,
84 ?who,
85 ?maybe_context,
86 "withdraw_asset",
87 );
88
89 let instance_id = Matcher::matches_instance(what)?;
90 let who = AccountIdConverter::convert_location(who)
91 .ok_or(MatchError::AccountIdConversionFailed)?;
92
93 InstanceOps::stash(&instance_id, IfOwnedBy::check(who))
94 .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
95
96 Ok(what.clone().into())
97 }
98
99 fn internal_transfer_asset(
100 what: &Asset,
101 from: &Location,
102 to: &Location,
103 context: &XcmContext,
104 ) -> Result<xcm_executor::AssetsInHolding, XcmError> {
105 tracing::trace!(
106 target: LOG_TARGET,
107 ?what,
108 ?from,
109 ?to,
110 ?context,
111 "internal_transfer_asset",
112 );
113
114 let instance_id = Matcher::matches_instance(what)?;
115 let from = AccountIdConverter::convert_location(from)
116 .ok_or(MatchError::AccountIdConversionFailed)?;
117 let to = AccountIdConverter::convert_location(to)
118 .ok_or(MatchError::AccountIdConversionFailed)?;
119
120 InstanceOps::update(&instance_id, ChangeOwnerFrom::check(from), &to)
121 .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
122
123 Ok(what.clone().into())
124 }
125}
126
127pub struct UniqueInstancesDepositAdapter<AccountId, AccountIdConverter, Id, InstanceCreateOp>(
132 PhantomData<(AccountId, AccountIdConverter, Id, InstanceCreateOp)>,
133);
134
135impl<AccountId, AccountIdConverter, Id, InstanceCreateOp> TransactAsset
136 for UniqueInstancesDepositAdapter<AccountId, AccountIdConverter, Id, InstanceCreateOp>
137where
138 AccountIdConverter: ConvertLocation<AccountId>,
139 InstanceCreateOp:
140 Create<WithConfig<ConfigValue<Owner<AccountId>>, DeriveAndReportId<NonFungibleAsset, Id>>>,
141{
142 fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
143 tracing::trace!(
144 target: LOG_TARGET,
145 ?what,
146 ?who,
147 ?context,
148 "deposit_asset",
149 );
150
151 let asset = match what.fun {
152 Fungibility::NonFungible(asset_instance) => (what.id.clone(), asset_instance),
153 _ => return Err(MatchError::AssetNotHandled.into()),
154 };
155
156 let who = AccountIdConverter::convert_location(who)
157 .ok_or(MatchError::AccountIdConversionFailed)?;
158
159 InstanceCreateOp::create(WithConfig::new(
160 Owner::with_config_value(who),
161 DeriveAndReportId::from(asset),
162 ))
163 .map(|_reported_id| ())
164 .map_err(|e| XcmError::FailedToTransactAsset(e.into()))
165 }
166}