@paraspell/sdk-pjs
SDK for handling XCM asset transfers across Polkadot and Kusama ecosystems.
Supporting every XCM Active Parachain [list]
SDK documentation [here]
Installation
Install dependencies
ParaSpell XCM SDK is the 🥇 in the ecosystem to support both PolkadotJS and PolkadotAPI.
This version of SDK uses PolkadotJS if you wish to use PolkadotAPI version please reffer to following package.
pnpm | npm install || yarn add @polkadot/api @polkadot/types @polkadot/api-base @polkadot/util @polkadot/util-crypto
Install SDK
pnpm | npm install || yarn add @paraspell/sdk-pjs
Importing package to your project
Builder pattern:
import { Builder } from '@paraspell/sdk-pjs'
Other patterns:
import * as paraspell from '@paraspell/sdk-pjs'
const paraspell = require('@paraspell/sdk-pjs')
Interaction with further asset symbol abstraction:
import { Native, Foreign, ForeignAbstract } from '@paraspell/sdk-pjs';
Implementation
NOTES:
- Local transfers are now available for every currency and every chain. To try them, simply use the same origin and destination parameters.
- Transfer info queries are now all in the Builder pattern and don't require any imports other than the builder.
- You can now query Ethereum asset balances on Ethereum via balance query
- The Builder() now accepts an optional configuration object (To enhance localhost experience and testing). This object can contain apiOverrides and a development flag. More information in the "Localhost test setup" section.
Latest news:
- V10 > V11 Migration guide https://paraspell.github.io/docs/migration/v10-to-v11.html
- Brand new asset decimal abstraction introduced. It can be turned on in Builder config. Will be turned on by default in next major release.
Sending XCM
For full documentation with examples on this feature head over to official documentation.
Transfer assets from Parachain to Parachain
const builder = Builder()
.from(CHAIN)
.to(CHAIN | Location object )
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | {location: Override('Custom Location'), amount: amount } | [{currencySelection , amount: amount }, {currencySelection}, ..])
.address(address | Location object )
.senderAddress(address)
const tx = await builder.build()
await builder.disconnect()
Transfer assets from the Relay chain to the Parachain
const builder = Builder()
.from(RELAY_CHAIN)
.to(CHAIN | Location object)
.currency({symbol: 'DOT', amount: amount })
.address(address | Location object)
const tx = await builder.build()
await builder.disconnect()
Transfer assets from Parachain to Relay chain
const builder = Builder()
.from(CHAIN)
.to(RELAY_CHAIN)
.currency({symbol: 'DOT', amount: amount })
.address(address | Location object)
const tx = await builder.build()
await builder.disconnect()
Local transfers
const builder = Builder()
.from(CHAIN)
.to(CHAIN)
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | {location: Override('Custom Location'), amount: amount } | [{currencySelection , amount: amount }, {currencySelection}, ..])
.address(address)
const tx = await builder.build()
await builder.disconnect()
Batch calls
const builder = Builder()
.from(CHAIN)
.to(CHAIN_2)
.currency({currencySelection, amount})
.address(address | Location object)
.addToBatch()
.from(CHAIN)
.to(CHAIN_3)
.currency({currencySelection, amount})
.address(address | Location object)
.addToBatch()
const tx = await builder.buildBatch({
mode: BatchMode.BATCH_ALL
})
await builder.disconnect()
Asset claim:
const builder = Builder()
.claimFrom(CHAIN)
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | [{currencySelection , amount: amount }, {currencySelection}, ..]
)
.address(address | Location object)
const tx = await builder.build()
await builder.disconnect()
Dry run your XCM Calls:
const result = await Builder()
.from(CHAIN)
.to(CHAIN_2)
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | {location: Override('Custom Location'), amount: amount } | {[{currencySelection, isFeeAsset?: true , amount: amount }]})
.address(ADDRESS)
.senderAddress(SENDER_ADDRESS)
.dryRun()
import { hasDryRunSupport } from "@paraspell/sdk";
const result = hasDryRunSupport(chain)
Dry run preview:
More on this feature in official documentation
const result = await Builder()
.from(CHAIN)
.to(CHAIN_2)
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | {location: Override('Custom Location'), amount: amount } | {[{currencySelection, isFeeAsset?: true , amount: amount }]})
.address(ADDRESS)
.senderAddress(SENDER_ADDRESS)
.dryRunPreview()
Localhost test setup
SDK offers enhanced localhost support. You can pass an object containing overrides for all WS endpoints (Including hops) used in the test transfer. This allows for advanced localhost testing such as localhost dry-run or xcm-fee queries. More information about available options can be found in the official documentation.
const builder = await Builder({
development: true,
decimalAbstraction: true
apiOverrides: {
Hydration:
BridgeHubPolkadot:
}
})
.from(CHAIN)
.to(CHAIN)
.currency({id: currencyID, amount: amount } | {symbol: currencySymbol, amount: amount } | {symbol: Native('currencySymbol'), amount: amount } | {symbol: Foreign('currencySymbol'), amount: amount } | {symbol: ForeignAbstract('currencySymbol'), amount: amount } | {location: AssetLocationString, amount: amount | AssetLocationJson, amount: amount } | {location: Override('Custom Location'), amount: amount } | [{currencySelection, isFeeAsset?: true , amount: amount }])
.address(address)
const tx = await builder.build()
await builder.disconnect()
XCM Fee queries
For full documentation with examples on this feature, head to official documentation.
XCM Transfer info
const info = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getTransferInfo()
Transferable amount
const transferable = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getTransferableAmount()
Minimal transferable amount
const transferable = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getMinTransferableAmount()
Receivable amount
const receivable = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getReceivableAmount()
Verify ED on destination
const ed = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.verifyEdOnDestination()
XCM Fee (Origin and Dest.)
More accurate query using DryRun
const fee = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getXcmFee()
Less accurate query using Payment info
const fee = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getXcmFeeEstimate()
XCM Fee (Origin only)
More accurate query using DryRun
const fee = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getOriginXcmFee()
Less accurate query using Payment info
const fee = await Builder()
.from(ORIGIN_CHAIN)
.to(DESTINATION_CHAIN)
.currency(CURRENCY)
.address(RECIPIENT_ADDRESS)
.senderAddress(SENDER_ADDRESS)
.getOriginXcmFeeEstimate()
Asset balance
import { getAssetBalance } from "@paraspell/sdk-pjs";
const balance = await getAssetBalance({address, chain, currency , api });
Ethereum bridge fees
import { getParaEthTransferFees } from "@paraspell/sdk-pjs";
const fees = await getParaEthTransferFees()
Existential deposit queries
import { getExistentialDeposit } from "@paraspell/sdk-pjs";
const ed = getExistentialDeposit(chain, currency?)
Convert SS58 address
import { convertSs58 } from "@paraspell/sdk-pjs";
let result = convertSs58(address, chain)
Asset queries:
For full documentation with examples on this feature head over to official documentation.
import { getSupportedDestinations, getFeeAssets, getAssetsObject, getAssetId, getRelayChainSymbol, getNativeAssets, getNativeAssets, getOtherAssets, getAllAssetsSymbols, hasSupportForAsset, getAssetDecimals, getParaId, getTChain, getAssetLocation, CHAINS, findAssetInfo, findAssetInfoOrThrow } from '@paraspell/sdk-pjs'
getSupportedDestinations(CHAIN, CURRENCY)
getFeeAssets(CHAIN)
getAssetLocation(CHAIN, { symbol: symbol } | { id: assetId })
findAssetInfo(CHAIN, CURRENCY, DESTINATION?)
findAssetInfoOrThrow(CHAIN, CURRENCY, DESTINATION?)
getAssetsObject(CHAIN)
getAssetId(CHAIN, ASSET_SYMBOL)
getRelayChainSymbol(CHAIN)
getNativeAssets(CHAIN)
getOtherAssets(CHAIN)
getAllAssetsSymbols(CHAIN)
hasSupportForAsset(CHAIN, ASSET_SYMBOL)
getAssetDecimals(CHAIN, ASSET_SYMBOL)
getParaId(CHAIN)
getTChain(paraID: number, ecosystem: 'Polkadot' | 'Kusama' | 'Ethereum' | 'Paseo' | 'Westend')
CHAINS
Parachain XCM Pallet queries
For full documentation with examples on this feature head over to official documentation.
import { getDefaultPallet, getSupportedPallets, getPalletIndex, getNativeAssetsPallet, getOtherAssetsPallets, SUPPORTED_PALLETS } from '@paraspell/sdk-pjs';
getDefaultPallet(CHAIN)
getSupportedPallets(CHAIN)
getPalletIndex(CHAIN)
getNativeAssetsPallet(chain: TChain)
getOtherAssetsPallets(CHAIN)
console.log(SUPPORTED_PALLETS)
💻 Tests
-
Run compilation using pnpm compile
-
Run linter using pnpm lint
-
Run unit tests using pnpm test
-
Run end-to-end tests using pnpm test:e2e
-
Run all core tests and checks using pnpm runAll
XCM SDK can be tested in Playground.
Contribute to XCM Tools and earn rewards 💰
We run an open Bug Bounty Program that rewards contributors for reporting and fixing bugs in the project. More information on bug bounty can be found in the official documentation.
Get Support 🚑
License
Made with 💛 by ParaSpell✨
Published under MIT License.
Supported by