feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit 286de54384
6841 changed files with 1848356 additions and 0 deletions
@@ -0,0 +1,166 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
use core::marker::PhantomData;
use frame_support::traits::tokens::asset_ops::{
common_strategies::{
ChangeOwnerFrom, ConfigValue, DeriveAndReportId, IfOwnedBy, Owner, WithConfig,
WithConfigValue,
},
AssetDefinition, Create, Restore, Stash, Update,
};
use xcm::latest::prelude::*;
use xcm_executor::traits::{ConvertLocation, Error as MatchError, MatchesInstance, TransactAsset};
use super::NonFungibleAsset;
const LOG_TARGET: &str = "xcm::unique_instances";
/// The `UniqueInstancesAdapter` implements the [`TransactAsset`] for existing unique instances
/// (NFT-like entities), for which the `Matcher` can deduce the instance ID from the XCM
/// [`AssetId`].
///
/// The adapter uses the following asset operations:
/// * [`Restore`] with the strategy to restore the instance to a given owner.
/// * [`Update`] with the strategy to change the instance's owner from one to another.
/// * [`Stash`] with the strategy to check the current owner before stashing.
///
/// Note on teleports: This adapter doesn't implement teleports since unique instances have
/// associated data that also should be teleported. Currently, neither XCM can transfer such data
/// nor does a standard approach exist in the ecosystem for this use case.
pub struct UniqueInstancesAdapter<AccountId, AccountIdConverter, Matcher, InstanceOps>(
PhantomData<(AccountId, AccountIdConverter, Matcher, InstanceOps)>,
);
impl<AccountId, AccountIdConverter, Matcher, InstanceOps> TransactAsset
for UniqueInstancesAdapter<AccountId, AccountIdConverter, Matcher, InstanceOps>
where
AccountId: 'static,
AccountIdConverter: ConvertLocation<AccountId>,
Matcher: MatchesInstance<InstanceOps::Id>,
InstanceOps: AssetDefinition
+ Restore<WithConfig<ConfigValue<Owner<AccountId>>>>
+ Update<ChangeOwnerFrom<AccountId>>
+ Stash<IfOwnedBy<AccountId>>,
{
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
tracing::trace!(
target: LOG_TARGET,
?what,
?who,
?context,
"deposit_asset",
);
let instance_id = Matcher::matches_instance(what)?;
let who = AccountIdConverter::convert_location(who)
.ok_or(MatchError::AccountIdConversionFailed)?;
InstanceOps::restore(&instance_id, WithConfig::from(Owner::with_config_value(who)))
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))
}
fn withdraw_asset(
what: &Asset,
who: &Location,
maybe_context: Option<&XcmContext>,
) -> Result<xcm_executor::AssetsInHolding, XcmError> {
tracing::trace!(
target: LOG_TARGET,
?what,
?who,
?maybe_context,
"withdraw_asset",
);
let instance_id = Matcher::matches_instance(what)?;
let who = AccountIdConverter::convert_location(who)
.ok_or(MatchError::AccountIdConversionFailed)?;
InstanceOps::stash(&instance_id, IfOwnedBy::check(who))
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
Ok(what.clone().into())
}
fn internal_transfer_asset(
what: &Asset,
from: &Location,
to: &Location,
context: &XcmContext,
) -> Result<xcm_executor::AssetsInHolding, XcmError> {
tracing::trace!(
target: LOG_TARGET,
?what,
?from,
?to,
?context,
"internal_transfer_asset",
);
let instance_id = Matcher::matches_instance(what)?;
let from = AccountIdConverter::convert_location(from)
.ok_or(MatchError::AccountIdConversionFailed)?;
let to = AccountIdConverter::convert_location(to)
.ok_or(MatchError::AccountIdConversionFailed)?;
InstanceOps::update(&instance_id, ChangeOwnerFrom::check(from), &to)
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
Ok(what.clone().into())
}
}
/// The `UniqueInstancesDepositAdapter` implements the [`TransactAsset`] to create unique instances
/// (NFT-like entities), for which no `Matcher` can deduce the instance ID from the XCM
/// [`AssetId`]. Instead, this adapter requires the `InstanceCreateOp` to create an instance using
/// [`NonFungibleAsset`] as ID derivation parameter.
pub struct UniqueInstancesDepositAdapter<AccountId, AccountIdConverter, Id, InstanceCreateOp>(
PhantomData<(AccountId, AccountIdConverter, Id, InstanceCreateOp)>,
);
impl<AccountId, AccountIdConverter, Id, InstanceCreateOp> TransactAsset
for UniqueInstancesDepositAdapter<AccountId, AccountIdConverter, Id, InstanceCreateOp>
where
AccountIdConverter: ConvertLocation<AccountId>,
InstanceCreateOp:
Create<WithConfig<ConfigValue<Owner<AccountId>>, DeriveAndReportId<NonFungibleAsset, Id>>>,
{
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
tracing::trace!(
target: LOG_TARGET,
?what,
?who,
?context,
"deposit_asset",
);
let asset = match what.fun {
Fungibility::NonFungible(asset_instance) => (what.id.clone(), asset_instance),
_ => return Err(MatchError::AssetNotHandled.into()),
};
let who = AccountIdConverter::convert_location(who)
.ok_or(MatchError::AccountIdConversionFailed)?;
InstanceCreateOp::create(WithConfig::new(
Owner::with_config_value(who),
DeriveAndReportId::from(asset),
))
.map(|_reported_id| ())
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))
}
}