Migration Guide v11 β‘ v12 β
This guide covers all breaking changes and new features introduced in version v12 of the ParaSpell XCM Tools.
These changes affect XCM SDK, XCM API, XCM Router, and XCM Analyser.
Overview of Breaking Changes β
v12 introduces the following major changes:
- Removal of deprecated
TNodeafter its prior replacement byTChain. - Removal of
currency: stringfields from XCM Fee and Dry-run queries. - Removal of legacy
assetHubandbridgeHubobjects. - Rename of balance query:
getAssetBalancerenamed togetBalance.- Removal of
getNativeAssetBalanceandgetForeignAssetBalance. currencyparameter is now optional and defaults to the chainβs native asset.
- Migration to ESM-only modules across SDKs and Router (CommonJS no longer supported, except for XCM Analyser which now fully supports CommonJS).
- Deprecation of payment-info-based XCM fee estimators (
getXcmFeeEstimate,getOriginXcmFeeEstimate). - Asset registry unification:
- Removal of
nativeAssetsandforeignAssets. - All assets are now stored under a single
assets[]array.
- Removal of
- Refactored and expanded error model, replacing generic errors with more specific error classes.
- Mythos asset selection restricted to Substrate location only; Ethereum MYTH location is no longer accepted.
Each topic is detailed below.
1. Removal of deprecated TNode types (Issue 1167) β
What changed β
In earlier versions, the SDK exposed TNode types to represent chain identifiers.
During v11, it was replaced by TChain types and marked as deprecated.
In v12, TNode types have been fully removed. All available TChain types can be found listed here.
β Action Required:
- Replace all usages of
TNodewithTChaintypes.
2. Removal of currency: Symbol field from XCM Fee queries and Dry-run queries (Issue 1193) β
What changed β
In early versions of our XCM Fee queries, we introduced a currency identifier in the form of a symbol. As features grew more robust, a full asset object became necessary, mainly because the primary selection method is by location. Some chains have multiple assets with similar or identical symbols, the only difference between them being capital or lowercase letters. The currency: symbol field grew obsolete after the full asset object was introduced. Keeping it caused duplication and confusion.
Previously, query responses included both:
- a
currency: "SYMBOL"string field, and - a full
assetobject with detailed metadata.
Affected queries: XCM Fee queries and Dry-run queries.
Example Before β
{
"currency": "ASTR",
"asset": {
"symbol": "ASTR",
"isNative": true,
"decimals": 18,
"existentialDeposit": "1000000",
"location": {
"parents": 1,
"interior": {
"X1": [{ "Parachain": 2006 }]
}
}
}
}Example after β
{
"asset": {
"symbol": "ASTR",
"isNative": true,
"decimals": 18,
"existentialDeposit": "1000000",
"location": {
"parents": 1,
"interior": {
"X1": [{ "Parachain": 2006 }]
}
}
}
}β Action Required:
Remove usage of the currency field.
Use asset.symbol wherever currency was previously used.
3. Unified Multi-Hop representation (Issue 1168) β
Previously, we only had AssetHub and BridgeHub as possible hop chains in XCM Fee and Dry-run queries. As the features grew more robust, we added a hop array that is more generic and could house any parachain as a hop. We removed the AssetHub and BridgeHub objects because they would occur redundantly, both on their own and also in the hops array, which caused unnecessary confusion.
In v12, hops[] becomes the single canonical structure.assetHub and bridgeHub top-level objects are removed.
Example Before β
{
"origin": {
"weight": {
"refTime": "30975850052",
"proofSize": "7590"
},
"fee": "82694150037",
"feeType": "dryRun",
"sufficient": false,
"currency": "BNC",
"asset": {
"symbol": "BNC",
"decimals": 12,
"existentialDeposit": "10000000000",
"location": {
"parents": 1,
"interior": {
"X2": [
{
"Parachain": 2030
},
{
"GeneralKey": {
"length": 2,
"data": "0x0001000000000000000000000000000000000000000000000000000000000000"
}
}
]
}
},
"isNative": true,
"isFeeAsset": true
}
},
"assetHub": {
"fee": "79429",
"feeType": "dryRun",
"currency": "USDt",
"asset": {
"assetId": "1984",
"symbol": "USDt",
"decimals": 6,
"location": {
"parents": 1,
"interior": {
"X3": [
{
"Parachain": 1000
},
{
"PalletInstance": 50
},
{
"GeneralIndex": 1984
}
]
}
},
"existentialDeposit": "10000",
"isFeeAsset": true
}
},
"destination": {
"fee": "393",
"feeType": "dryRun",
"currency": "USDT",
"asset": {
"assetId": "10",
"symbol": "USDT",
"decimals": 6,
"existentialDeposit": "10000",
"location": {
"parents": 1,
"interior": {
"X3": [
{
"Parachain": 1000
},
{
"PalletInstance": 50
},
{
"GeneralIndex": 1984
}
]
}
},
"isFeeAsset": true,
"alias": "USDT1"
}
},
"hops": [
{
"chain": "AssetHubPolkadot",
"result": {
"fee": "79429",
"feeType": "dryRun",
"currency": "USDt",
"asset": {
"assetId": "1984",
"symbol": "USDt",
"decimals": 6,
"location": {
"parents": 1,
"interior": {
"X3": [
{
"Parachain": 1000
},
{
"PalletInstance": 50
},
{
"GeneralIndex": 1984
}
]
}
},
"existentialDeposit": "10000",
"isFeeAsset": true
}
}
}
]
}Example after: β
{
"origin": {
"weight": {
"refTime": "30975850052",
"proofSize": "7590"
},
"fee": "82694150037",
"feeType": "dryRun",
"sufficient": false,
"asset": {
"symbol": "BNC",
"decimals": 12,
"existentialDeposit": "10000000000",
"location": {
"parents": 1,
"interior": {
"X2": [
{
"Parachain": 2030
},
{
"GeneralKey": {
"length": 2,
"data": "0x0001000000000000000000000000000000000000000000000000000000000000"
}
}
]
}
},
"isNative": true,
"isFeeAsset": true
}
},
"destination": {
"fee": "393",
"feeType": "dryRun",
"asset": {
"assetId": "10",
"symbol": "USDT",
"decimals": 6,
"existentialDeposit": "10000",
"location": {
"parents": 1,
"interior": {
"X3": [
{
"Parachain": 1000
},
{
"PalletInstance": 50
},
{
"GeneralIndex": 1984
}
]
}
},
"isFeeAsset": true,
"alias": "USDT1"
}
},
"hops": [
{
"chain": "AssetHubPolkadot",
"result": {
"fee": "79429",
"feeType": "dryRun",
"asset": {
"assetId": "1984",
"symbol": "USDt",
"decimals": 6,
"location": {
"parents": 1,
"interior": {
"X3": [
{
"Parachain": 1000
},
{
"PalletInstance": 50
},
{
"GeneralIndex": 1984
}
]
}
},
"existentialDeposit": "10000",
"isFeeAsset": true
}
}
}
]
}β Action Required:
Remove all references to assetHub and bridgeHub objects in XCM Fee queries or Dry-run queries.
Adapt code to retrieve hop fees and assets exclusively from hops[] array.
4. Rename of Balance query and removal of Native/Foreign balance sub-queries (Issue 1477) β
The SDK and API previously exposed native and foreign balance sub-queries.
These were already undocumented, and in v12 they have been fully removed. The unified getBalance query handles both cases automatically and is preferred.
Since they have been removed, we took the opportunity to make the balance query name more intuitive. It is now renamed from getAssetBalance to getBalance.
Additionally, the currency parameter in the balance query is now optional.
If omitted, the query defaults to the selection of the chainβs native asset.
- getAssetBalance()
+ getBalance()XCM API Endpoint Change β
The XCM API balance query endpoint has also been updated for consistency with the renamed balance query:
- POST /v4/balance/:chain/asset
+ POST /v5/balance/:chainβ Action Required:
- Replace all usages of the
getNativeAssetBalanceorgetForeignAssetBalancequeries with thegetBalancequery. - Rename
getAssetBalancetogetBalance. - If you previously specified a currency only to retrieve the native asset balance (of the specified chain), you can now omit it.
- Please update any API integrations to use the new
/v5/balance/:chainendpoint.
Summary β
Balance lookups are now simplified.
The SDK determines whether native or foreign resolution is required and defaults to the chainβs native asset when no currency is specified.
5. Migration to ESM-Only Modules (Issue 1499) β
The SDKs and Router have migrated to ESM-only.
This aligns with modern JavaScript standards and is required to upgrade dependencies that are already ESM-only, including:
@noble/curvesv2@noble/hashesv2
Classic CommonJS (require(...)) is no longer supported by the SDKs or Router.
We have added support for CommonJS in XCM Analyser (as that package is mostly vanilla).
β Action Required:
- Update your environment to support ESM (Node.js β₯ 16+,
"type": "module"inpackage.json, or use.mjs). - Replace
require()imports withimportsyntax. - If bundling, ensure your bundler is configured for ESM packages.
- If your project uses CommonJS and had to adapt to ESM because of the XCM Analyser library, you can convert back to CommonJS, as Analyser now also supports CommonJS.
6. Deprecation of payment info XCM fee estimators (Issue 1166) β
The following fee estimation functions are now deprecated:
getXcmFeeEstimategetOriginXcmFeeEstimate
These functions relied solely on payment info, which is often inaccurate for XCM.
Available alternatives:
getXcmFeegetOriginXcmFee
These use dry-run fee estimation when available and fall back to payment info only when necessary.
β Action Required:
- Replace all deprecated function calls with listed alternatives.
7. Asset registry overhaul and unification (Issue 1361) β
Previously, our asset registry divided assets under each chain into two separate arrays:
nativeAssetsotherAssets
This structure was difficult to maintain and unnecessary.
In v12, asset definitions are unified under a single assets array, where native assets are identified by an isNative: true flag. This allowed us to significantly improve code quality, save package space, and optimize certain types and functions that needed to pick between the two arrays.
Example Before β
"Polkadot": {
"relaychainSymbol": "DOT",
"nativeAssetSymbol": "DOT",
"isEVM": false,
"ss58Prefix": 0,
"supportsDryRunApi": true,
"supportsXcmPaymentApi": true,
"nativeAssets": [
{
"symbol": "DOT",
"isNative": true,
"decimals": 10,
"existentialDeposit": "10000000000",
"location": {
"parents": 1,
"interior": { "Here": null }
}
}
],
"otherAssets": []
}Example after: β
"Polkadot": {
"relaychainSymbol": "DOT",
"nativeAssetSymbol": "DOT",
"isEVM": false,
"ss58Prefix": 0,
"supportsDryRunApi": true,
"supportsXcmPaymentApi": true,
"assets": [
{
"symbol": "DOT",
"isNative": true,
"decimals": 10,
"existentialDeposit": "10000000000",
"location": {
"parents": 1,
"interior": { "Here": null }
}
}
]
}β Action Required:
Update any code referencing nativeAssets or otherAssets from SDKs or Asset package.
Use the assets array exclusively and filter by isNative if you are searching for the native asset within the chain.
8. Error model refactor and expansion (Issue 1338) β
Several broad or ambiguous errors were removed, and more specific and descriptive error classes have been added.
-`ChainNotSupportedError`
-`IncompatibleChainsError`
-`InvalidParameterError`
+ `BatchValidationError`
+ `FeatureTemporarilyDisabledError`
+ `MissingParameterError`
+ `NumberFormatError`
+ `OverrideConflictError`
+ `ProviderUnavailableError`
+ `RoutingResolutionError`
+ `RuntimeApiUnavailableError`
+ `UnsupportedOperationError`The new error model provides more accurate diagnostics and allows integrators to distinguish between configuration problems, runtime API unavailability, routing failures, invalid user inputs, and provider outages.
Full definitions for all errors can be found here.
β Action Required:
- Update error-handling logic to catch and react to the new error classes.
- Remove or refactor checks relying on the deprecated generic errors.
9. Mythos asset selection restricted to Substrate location only β
Prior to v12, Mythos transfers to Ethereum could be selected using either:
- Its native parachain location, or
- An Ethereum MYTH location, enabled by a temporary compatibility block in the SDK:
// Temporary condition for Mythos to allow selecting by Ethereum MYTH location
// Will be removed in v12
if (chain === 'Mythos') {
const mythEthAsset = getOtherAssets('Ethereum').find(a => a.symbol === 'MYTH')
if (mythEthAsset && findAssetInfoByLoc([mythEthAsset], currency.location))
asset = nativeAssets[0]
}This change was done to optimize the code and to unify the selection of MYTH.
New Requirement β
Mythos must now be selected exclusively through its native location:
{
"parents": 1,
"interior": {
"X1": [
{ "Parachain": 3369 }
]
}
}No Longer Accepted β
Ethereum GlobalConsensus representation of MYTH can no longer be used to select MYTH.
{
"parents": 2,
"interior": {
"X2": [
{
"GlobalConsensus": {
"Ethereum": { "chainId": 1 }
}
},
{
"AccountKey20": {
"network": null,
"key": "0xba41ddf06b7ffd89d1267b5a93bfef2424eb2003"
}
}
]
}
}This ensures deterministic asset selection and minimizes possible future bugs.
β Action Required:
- Update any integration that selected Mythos via Ethereum MYTH location.
- Ensure all queries and XCM constructions use the provided substrate location only.
v12 Pull request β
For a more detailed overview, we list the v12 pull request.
