Skip to content

Migration Guide v12 ➑ v13 ​

This guide covers all breaking changes, API updates, and new features introduced in v13 of ParaSpell XCM Tools.

The update focuses on:

  • Simplifying the builder API
  • Removing deprecated and legacy functionality
  • Unifying Swap integration support for all XCM SDKs

Tracking issue (For deep dive code checking): ​

https://github.com/paraspell/xcm-tools/issues/1624

⚠️ Breaking Changes ​

πŸ› οΈ Specific XCM API breaking changes ​

The XCM API has now moved under the paraspell.xyz domain, so instead of https://api.lightspell.xyz/v5/assets/Astar you now use https://api.paraspell.xyz/v1/assets/Astar.

1. Builder API renaming ​

What changed ​
  • .senderAddress() β†’ .sender()
  • .address() β†’ .recipient()

This improves readability and aligns with natural terminology.

Before (v12) ​
ts
builder
  .senderAddress(sender)
  .address(recipient)
After (v13) ​
ts
builder
  .sender(sender)
  .recipient(recipient)

2. Fee estimation functions removed ​

What changed ​

All deprecated fee estimation functions (based on paymentInfo) have been removed.

List of functions and what they should be replaced by:

ts
.getXcmFeeEstimate() ->Β .getXcmFee()
.getOriginXcmFeeEstimate() ->Β .getOriginXcmFee()
Migration ​

3. /router API endpoint removed ​

What changed ​

The /router API endpoint has been removed.

Routing functionality is now fully integrated into the SDK builder.

Available as swap endpoint in API.

Migration ​

4. RouterBuilder usage change ​

What changed ​
  • RouterBuilder is now generic
  • It is no longer intended to be used directly from the swap package
Before (v12) ​
ts
await RouterBuilder()
       .from(TSubstrateChain)   
       .to(TChain)    
       .currencyFrom(currencyFrom)   
       .currencyTo(currencyTo)   
       .amount(amount)  
       .slippagePct(pct)  
       .senderAddress(injectorAddress) 
       .recipientAddress(recipientAddress) 
       .signer(signer)  
       .onStatusChange((status: TRouterEvent) => {  
         console.log(status.type);  
         console.log(status.routerPlan);   
         console.log(status.chain);
         console.log(status.destinationChain);  
         console.log(status.currentStep);    
       })
       .buildAndSend()
After (v13) ​
ts
const builder = Builder()
      .from(TSubstrateChain) 
      .to(TChain)
      .currency(CURRENCY_SPEC)
      .recipient(address)
      .sender(address) 
      .swap({
          currencyTo: CURRENCY_SPEC,
      })

const tx = await builder.buildAll()

await builder.disconnect()

5. TSendOptions renamed ​

What changed ​
ts
TSendOptions β†’ TTransferOptions
Migration ​
  • Replace all usages of TSendOptions with TTransferOptions

6. Deprecated asset helpers ​

What changed ​

The following functions are now deprecated:

  • hasSupportForAsset
  • getAssetId
  • getAssetDecimals

These are deprecated in favor of findAssetInfo.

Migration ​
ts
// ❌ Old
hasSupportForAsset(...)
getAssetId(...)
getAssetDecimals(...)

// βœ… New (Has all three information in one place)
findAssetInfo(...)

7. findAssetInfo update ​

What changed ​
  • Third parameter destination is now optional
Before (v12) ​
ts
findAssetInfo(chain, CURRENCY_SPEC, destination)
After (v13) ​
ts
// If not given, nothing changes (unless destination is Ethereum and you are searching by Asset symbol, make sure to provide it in that case because you can get a duplicate asset error)
findAssetInfo(chain, CURRENCY_SPEC, destination?)

8. getXcmFee response change ​

What changed ​
  • isExchange flag has been moved
  • It now exists inside each hop.result
Before (v12) ​

Accessing result:

ts
result.hops[i].isExchange

Example result:

ts
{
  "origin": {
    "weight": {
      "refTime": "18446744073709551615",
      "proofSize": "22338"
    },
    "fee": "14901746512880889",
    "feeType": "dryRun",
    "sufficient": false,
    "asset": {
      "symbol": "ASTR",
      "isNative": true,
      "decimals": 18,
      "existentialDeposit": "1000000",
      "location": {
        "parents": 1,
        "interior": {
          "X1": [
            {
              "Parachain": 2006
            }
          ]
        }
      }
    }
  },
  "destination": {
    "fee": "149",
    "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": "327948830",
        "feeType": "dryRun",
        "sufficient": true,
        "asset": {
          "symbol": "DOT",
          "isNative": true,
          "decimals": 10,
          "existentialDeposit": "100000000",
          "location": {
            "parents": 1,
            "interior": {
              "Here": null
            }
          },
          "isFeeAsset": true
        },
        "forwardedXcms": [],
        "weight": {
          "refTime": "530928826",
          "proofSize": "16264"
        },
        "isExchange": true
      },
      "isExchange": true
    }
  ]
}
After (v13) ​

Accessing result:

ts
result.hops[i].result.isExchange

Example result:

ts
{
  "origin": {
    "weight": {
      "refTime": "18446744073709551615",
      "proofSize": "22338"
    },
    "fee": "14901746512880889",
    "feeType": "dryRun",
    "sufficient": false,
    "asset": {
      "symbol": "ASTR",
      "isNative": true,
      "decimals": 18,
      "existentialDeposit": "1000000",
      "location": {
        "parents": 1,
        "interior": {
          "X1": [
            {
              "Parachain": 2006
            }
          ]
        }
      }
    }
  },
  "destination": {
    "fee": "149",
    "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": "327948830",
        "feeType": "dryRun",
        "sufficient": true,
        "asset": {
          "symbol": "DOT",
          "isNative": true,
          "decimals": 10,
          "existentialDeposit": "100000000",
          "location": {
            "parents": 1,
            "interior": {
              "Here": null
            }
          },
          "isFeeAsset": true
        },
        "forwardedXcms": [],
        "weight": {
          "refTime": "530928826",
          "proofSize": "16264"
        },
        "isExchange": true
      },
    }
  ]
}
Migration ​
  • Update any logic relying on isExchange to use the new location

9. Exchange parameter now takes TExchangeChain ​

What changed ​
  • .exchange() parameter in Swap package now takes TExchangeChain parameter, removing Dex suffix.
Before (v12) ​
ts
.exchange("AssetHubPolkadotDex")
After (v13) ​
ts
.exchange("AssetHubPolkadot")
Migration ​

Use TExchangeChain type:

ts
.exchange("AssetHubPolkadot")

✨ New Defaults & Behavior Changes ​

10. Abstract decimals enabled by default ​

What changed ​
  • abstractDecimals is now enabled by default
Before (v12) ​
ts
abstractDecimals: false
After (v13) ​
ts
abstractDecimals: true
Migration ​

If you rely on raw decimals:

ts
abstractDecimals: false

πŸš€ New Features ​

11. signAndSubmitAll ​

What changed ​

A new method has been introduced:

ts
signAndSubmitAll()

Behavior ​

  • Returns an array of transaction hexes
  • Allows tracking of all submitted transactions

Comparison ​

ts
// v13
signAndSubmit()     // Used in one-click scenarios & basic transfers when a signer is provided to sender()
signAndSubmitAll()  // Used in two-click swap scenarios when a signer is provided to sender()