Check what a chain exposes before you trust an XCM route
A chain can accept a WebSocket connection, answer a balance query, and still have no way to build the transfer you asked for. The failure surfaces at build or encode time, after the amount and the recipient are set, and the message names a method rather than the missing capability.
Four transfer methods and two runtime APIs decide whether a route can be built, fee-estimated and dry run. One command prints them, with a live probe next to the flag the SDK actually uses.
The four transfer methods
The XCM SDK can call four extrinsics on PolkadotXcm or XcmPallet. Each covers a different route shape.
transfer_assets_using_type_and_then. Required for a relay asset on an origin that does not reserve it, and reached by some external-asset routes. When it is missing, those routes throwTypeAndThenUnavailableErrorinstead of building an invalid call.limited_reserve_transfer_assetsandreserve_transfer_assets. The reserve-transfer paths for foreign assets. The limited form carries a weight limit and is the one the SDK prefers.limited_teleport_assets. Teleports, used for trusted-chain routes where the asset is native on both sides.
The two runtime APIs
DryRunApi. How the SDK turns a built call into a fee and a success check. Without it, fee estimation falls back to other sources, and the type-and-then path loses the pass that would have replaced its fee placeholder. The public report on that path is xcm-tools#2353.XcmPaymentApi. The fee-query interface the SDK prefers when it exists. Without it, the SDK usespaymentInfoor dry run instead, and some execution paths check the flag before trusting a fee from this source.
Run it
The script is check-chain-capabilities.mjs, also published at github.com/ImBeasting/xcm-capability-checker with the 45-chain data and an MIT license. It uses @paraspell/sdk from npm and connects to each chain's default endpoint.
npm install @paraspell/sdk
node check-chain-capabilities.mjs Hydration Peaq Heima BifrostPolkadot
Example output
Run against four live Polkadot parachains on 29 October 2026:
Hydration (PolkadotXcm, HDX 12 decimals)
transfer_assets_using_type_and_then yes
limited_reserve_transfer_assets yes
reserve_transfer_assets yes
limited_teleport_assets yes
DryRunApi live yes registry yes
XcmPaymentApi live yes registry yes
Peaq (PolkadotXcm, PEAQ 18 decimals)
transfer_assets_using_type_and_then yes
limited_reserve_transfer_assets yes
reserve_transfer_assets yes
limited_teleport_assets yes
DryRunApi live no registry no
XcmPaymentApi live no registry no
Heima (PolkadotXcm, HEI 18 decimals)
transfer_assets_using_type_and_then yes
limited_reserve_transfer_assets yes
reserve_transfer_assets yes
limited_teleport_assets yes
DryRunApi live no registry no
XcmPaymentApi live no registry no
BifrostPolkadot (PolkadotXcm, BNC 12 decimals)
transfer_assets_using_type_and_then yes
limited_reserve_transfer_assets yes
reserve_transfer_assets yes
limited_teleport_assets yes
DryRunApi live yes registry yes
XcmPaymentApi live yes registry yes
All 45 chains in the SDK list, checked on 29 October 2026: the capability matrix. The exceptions are Pendulum (no type-and-then) and Heima, HeimaPaseo, Peaq and Pendulum (no DryRunApi or XcmPaymentApi).
How to read it
- Method no. The SDK falls back to another transfer path, or throws for routes that need the missing method. It does not build the call.
- Runtime API no. Fee estimation and dry run fall back. For type-and-then, a missing
DryRunApiis the path behind the placeholder report above. - Live and registry disagree. The SDK follows the registry, not the live probe. If a chain enabled a runtime API after the asset map was generated, the SDK still takes the fallback. Update
@paraspell/assetsor pass a custom chain with the correct flag. - A question mark. The probe hit an error it could not classify, usually a transient connection failure. Run it again.
- Everything missing. Check the endpoint. The probe reads the metadata the SDK would use, and a provider stuck at an old block serves an old metadata set. That is a provider problem, not a chain problem.
What it does not check
Asset listings, decimals, existential deposits, the destination's support for the asset, the reserve chain, XCM version negotiation, and whether a route exists at all. Those come from the asset map and the destination, not from the origin's metadata. A green table is a necessary condition, not a route test.
AI assistance was used to draft this article. The example output is from a real run, and the method names are taken from the SDK's own transfer type.
Want the whole surface checked?
Fixed-scope XCM audits with a failing test or call-path proof for every finding. The first verified finding is free.