Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XCM builder pattern improvement - Accept impl Into<T> instead of just T #3708

Merged
merged 12 commits into from
Apr 4, 2024
Merged
2 changes: 1 addition & 1 deletion polkadot/xcm/pallet-xcm/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ fn claim_assets_works() {
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())
.withdraw_asset((Here, SEND_AMOUNT))
.build();
// Even though assets are trapped, the extrinsic returns success.
assert_ok!(XcmPallet::execute_blob(
Expand Down
18 changes: 12 additions & 6 deletions polkadot/xcm/procedural/src/builder_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions polkadot/xcm/procedural/tests/builder_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions polkadot/xcm/src/v4/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
29 changes: 29 additions & 0 deletions prdoc/pr_3708.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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"
- name: "staging-xcm"
acatangiu marked this conversation as resolved.
Show resolved Hide resolved
Loading