Change `XcmDryRunApi::dry_run_extrinsic` to take a call instead (#4621)
Follow-up to the new `XcmDryRunApi` runtime API introduced in
https://github.com/paritytech/polkadot-sdk/pull/3872.
Taking an extrinsic means the frontend has to sign first to dry-run and
once again to submit.
This is bad UX which is solved by taking an `origin` and a `call`.
This also has the benefit of being able to dry-run as any account, since
it needs no signature.
This is a breaking change since I changed `dry_run_extrinsic` to
`dry_run_call`, however, this API is still only on testnets.
The crates are bumped accordingly.
As a part of this PR, I changed the name of the API from `XcmDryRunApi`
to just `DryRunApi`, since it can be used for general dry-running :)
Step towards https://github.com/paritytech/polkadot-sdk/issues/690.
Example of calling the API with PAPI, not the best code, just testing :)
```ts
// We just build a call, the arguments make it look very big though.
const call = localApi.tx.XcmPallet.transfer_assets({
dest: XcmVersionedLocation.V4({ parents: 0, interior: XcmV4Junctions.X1(XcmV4Junction.Parachain(1000)) }),
beneficiary: XcmVersionedLocation.V4({ parents: 0, interior: XcmV4Junctions.X1(XcmV4Junction.AccountId32({ network: undefined, id: Binary.fromBytes(encodeAccount(account.address)) })) }),
weight_limit: XcmV3WeightLimit.Unlimited(),
assets: XcmVersionedAssets.V4([{
id: { parents: 0, interior: XcmV4Junctions.Here() },
fun: XcmV3MultiassetFungibility.Fungible(1_000_000_000_000n) }
]),
fee_asset_item: 0,
});
// We call the API passing in a signed origin
const result = await localApi.apis.XcmDryRunApi.dry_run_call(
WestendRuntimeOriginCaller.system(DispatchRawOrigin.Signed(account.address)),
call.decodedCall
);
if (result.success && result.value.execution_result.success) {
// We find the forwarded XCM we want. The first one going to AssetHub in this case.
const xcmsToAssetHub = result.value.forwarded_xcms.find(([location, _]) => (
location.type === "V4" &&
location.value.parents === 0 &&
location.value.interior.type === "X1"
&& location.value.interior.value.type === "Parachain"
&& location.value.interior.value.value === 1000
))!;
// We can even find the delivery fees for that forwarded XCM.
const deliveryFeesQuery = await localApi.apis.XcmPaymentApi.query_delivery_fees(xcmsToAssetHub[0], xcmsToAssetHub[1][0]);
if (deliveryFeesQuery.success) {
const amount = deliveryFeesQuery.value.type === "V4" && deliveryFeesQuery.value.value[0].fun.type === "Fungible" && deliveryFeesQuery.value.value[0].fun.value.valueOf() || 0n;
// We store them in state somewhere.
setDeliveryFees(formatAmount(BigInt(amount)));
}
}
```
---------
Co-authored-by: Bastian Köcher <[email protected]>