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 changes ​

XCM API is now moved under 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

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 duplicite 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 array of transaction hexes
  • Allows tracking of all submitted transactions

Comparison ​

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