mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-08 03:08:06 +00:00
XCM builder pattern improvement - Accept impl Into<T> instead of just T (#3708)
The XCM builder pattern lets you build xcms like so:
```rust
let xcm = Xcm::builder()
.withdraw_asset((Parent, 100u128).into())
.buy_execution((Parent, 1u128).into())
.deposit_asset(All.into(), AccountId32 { id: [0u8; 32], network: None }.into())
.build();
```
All the `.into()` become quite annoying to have to write.
I accepted `impl Into<T>` instead of `T` in the generated methods from
the macro.
Now the previous example can be simplified as follows:
```rust
let xcm = Xcm::builder()
.withdraw_asset((Parent, 100u128))
.buy_execution((Parent, 1u128))
.deposit_asset(All, [0u8; 32])
.build();
```
---------
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: command-bot <>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
This commit is contained in:
committed by
GitHub
parent
bcb4d137c9
commit
c130ea9939
@@ -486,9 +486,8 @@ fn claim_assets_works() {
|
||||
let balances = vec![(ALICE, INITIAL_BALANCE)];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
// First trap some assets.
|
||||
let trapping_program = Xcm::<RuntimeCall>::builder_unsafe()
|
||||
.withdraw_asset((Here, SEND_AMOUNT).into())
|
||||
.build();
|
||||
let trapping_program =
|
||||
Xcm::<RuntimeCall>::builder_unsafe().withdraw_asset((Here, SEND_AMOUNT)).build();
|
||||
// Even though assets are trapped, the extrinsic returns success.
|
||||
assert_ok!(XcmPallet::execute_blob(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
|
||||
@@ -107,7 +107,8 @@ fn generate_builder_raw_impl(name: &Ident, data_enum: &DataEnum) -> TokenStream2
|
||||
.collect();
|
||||
let arg_types: Vec<_> = fields.unnamed.iter().map(|field| &field.ty).collect();
|
||||
quote! {
|
||||
pub fn #method_name(mut self, #(#arg_names: #arg_types),*) -> Self {
|
||||
pub fn #method_name(mut self, #(#arg_names: impl Into<#arg_types>),*) -> Self {
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
self.instructions.push(#name::<Call>::#variant_name(#(#arg_names),*));
|
||||
self
|
||||
}
|
||||
@@ -117,7 +118,8 @@ fn generate_builder_raw_impl(name: &Ident, data_enum: &DataEnum) -> TokenStream2
|
||||
let arg_names: Vec<_> = fields.named.iter().map(|field| &field.ident).collect();
|
||||
let arg_types: Vec<_> = fields.named.iter().map(|field| &field.ty).collect();
|
||||
quote! {
|
||||
pub fn #method_name(mut self, #(#arg_names: #arg_types),*) -> Self {
|
||||
pub fn #method_name(mut self, #(#arg_names: impl Into<#arg_types>),*) -> Self {
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
self.instructions.push(#name::<Call>::#variant_name { #(#arg_names),* });
|
||||
self
|
||||
}
|
||||
@@ -188,8 +190,9 @@ fn generate_builder_impl(name: &Ident, data_enum: &DataEnum) -> Result<TokenStre
|
||||
let arg_types: Vec<_> = fields.unnamed.iter().map(|field| &field.ty).collect();
|
||||
quote! {
|
||||
#(#docs)*
|
||||
pub fn #method_name(self, #(#arg_names: #arg_types),*) -> XcmBuilder<Call, LoadedHolding> {
|
||||
pub fn #method_name(self, #(#arg_names: impl Into<#arg_types>),*) -> XcmBuilder<Call, LoadedHolding> {
|
||||
let mut new_instructions = self.instructions;
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
new_instructions.push(#name::<Call>::#variant_name(#(#arg_names),*));
|
||||
XcmBuilder {
|
||||
instructions: new_instructions,
|
||||
@@ -203,8 +206,9 @@ fn generate_builder_impl(name: &Ident, data_enum: &DataEnum) -> Result<TokenStre
|
||||
let arg_types: Vec<_> = fields.named.iter().map(|field| &field.ty).collect();
|
||||
quote! {
|
||||
#(#docs)*
|
||||
pub fn #method_name(self, #(#arg_names: #arg_types),*) -> XcmBuilder<Call, LoadedHolding> {
|
||||
pub fn #method_name(self, #(#arg_names: impl Into<#arg_types>),*) -> XcmBuilder<Call, LoadedHolding> {
|
||||
let mut new_instructions = self.instructions;
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
new_instructions.push(#name::<Call>::#variant_name { #(#arg_names),* });
|
||||
XcmBuilder {
|
||||
instructions: new_instructions,
|
||||
@@ -249,8 +253,9 @@ fn generate_builder_impl(name: &Ident, data_enum: &DataEnum) -> Result<TokenStre
|
||||
fields.named.iter().map(|field| &field.ty).collect();
|
||||
quote! {
|
||||
#(#docs)*
|
||||
pub fn #method_name(self, #(#arg_names: #arg_types),*) -> XcmBuilder<Call, AnythingGoes> {
|
||||
pub fn #method_name(self, #(#arg_names: impl Into<#arg_types>),*) -> XcmBuilder<Call, AnythingGoes> {
|
||||
let mut new_instructions = self.instructions;
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
new_instructions.push(#name::<Call>::#variant_name { #(#arg_names),* });
|
||||
XcmBuilder {
|
||||
instructions: new_instructions,
|
||||
@@ -308,8 +313,9 @@ fn generate_builder_unpaid_impl(name: &Ident, data_enum: &DataEnum) -> Result<To
|
||||
Ok(quote! {
|
||||
impl<Call> XcmBuilder<Call, ExplicitUnpaidRequired> {
|
||||
#(#docs)*
|
||||
pub fn #unpaid_execution_method_name(self, #(#arg_names: #arg_types),*) -> XcmBuilder<Call, AnythingGoes> {
|
||||
pub fn #unpaid_execution_method_name(self, #(#arg_names: impl Into<#arg_types>),*) -> XcmBuilder<Call, AnythingGoes> {
|
||||
let mut new_instructions = self.instructions;
|
||||
#(let #arg_names = #arg_names.into();)*
|
||||
new_instructions.push(#name::<Call>::#unpaid_execution_ident { #(#arg_names),* });
|
||||
XcmBuilder {
|
||||
instructions: new_instructions,
|
||||
|
||||
@@ -22,11 +22,11 @@ use xcm::latest::prelude::*;
|
||||
#[test]
|
||||
fn builder_pattern_works() {
|
||||
let asset: Asset = (Here, 100u128).into();
|
||||
let beneficiary: Location = AccountId32 { id: [0u8; 32], network: None }.into();
|
||||
let beneficiary: Location = [0u8; 32].into();
|
||||
let message: Xcm<()> = Xcm::builder()
|
||||
.receive_teleported_asset(asset.clone().into())
|
||||
.receive_teleported_asset(asset.clone())
|
||||
.buy_execution(asset.clone(), Unlimited)
|
||||
.deposit_asset(asset.clone().into(), beneficiary.clone())
|
||||
.deposit_asset(asset.clone(), beneficiary.clone())
|
||||
.build();
|
||||
assert_eq!(
|
||||
message,
|
||||
@@ -53,8 +53,8 @@ fn default_builder_requires_buy_execution() {
|
||||
// To be able to do that, we need to use the explicitly unpaid variant
|
||||
let message: Xcm<()> = Xcm::builder_unpaid()
|
||||
.unpaid_execution(Unlimited, None)
|
||||
.withdraw_asset(asset.clone().into())
|
||||
.deposit_asset(asset.clone().into(), beneficiary.clone())
|
||||
.withdraw_asset(asset.clone())
|
||||
.deposit_asset(asset.clone(), beneficiary.clone())
|
||||
.build(); // This works
|
||||
assert_eq!(
|
||||
message,
|
||||
@@ -68,8 +68,8 @@ fn default_builder_requires_buy_execution() {
|
||||
// The other option doesn't have any limits whatsoever, so it should
|
||||
// only be used when you really know what you're doing.
|
||||
let message: Xcm<()> = Xcm::builder_unsafe()
|
||||
.withdraw_asset(asset.clone().into())
|
||||
.deposit_asset(asset.clone().into(), beneficiary.clone())
|
||||
.withdraw_asset(asset.clone())
|
||||
.deposit_asset(asset.clone(), beneficiary.clone())
|
||||
.build();
|
||||
assert_eq!(
|
||||
message,
|
||||
|
||||
@@ -530,6 +530,13 @@ impl<Interior: Into<Junctions>> From<AncestorThen<Interior>> for Location {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for Location {
|
||||
fn from(bytes: [u8; 32]) -> Self {
|
||||
let junction: Junction = bytes.into();
|
||||
junction.into()
|
||||
}
|
||||
}
|
||||
|
||||
xcm_procedural::impl_conversion_functions_for_location_v4!();
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
|
||||
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
|
||||
|
||||
title: XCM builder pattern automatically converts instruction parameters.
|
||||
|
||||
doc:
|
||||
- audience: Runtime Dev
|
||||
description: |
|
||||
Small quality of life improvement.
|
||||
Previously, an XCM could be built like this:
|
||||
```rust
|
||||
let xcm = Xcm::builder()
|
||||
.withdraw_asset((Parent, 100u128).into())
|
||||
.buy_execution((Parent, 1u128).into())
|
||||
.deposit_asset(All.into(), AccountId32 { id: [0u8; 32], network: None }.into())
|
||||
.build();
|
||||
```
|
||||
Now, it can be built like this:
|
||||
```rust
|
||||
let xcm = Xcm::builder()
|
||||
.withdraw_asset((Parent, 100u128))
|
||||
.buy_execution((Parent, 1u128))
|
||||
.deposit_asset(All, [0u8; 32])
|
||||
.build();
|
||||
```
|
||||
|
||||
crates:
|
||||
- name: "xcm-procedural"
|
||||
bump: minor
|
||||
- name: "staging-xcm"
|
||||
bump: minor
|
||||
Reference in New Issue
Block a user