0.1.0 • Published 1 year ago

xcm-sdk v0.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

XCM SDK

CircleCI Coverage Status CodeQL npm npm vulnerabilities License

About

XCM SDK is a tool that provides an interface to send XCM messages for Substrate based blockchains. This library is written in Typescript so it can be imported in a whole new set of applications or dApps that use Javascript/Typescript engines such as Node.js.

Get Started

Install

npm i xcm-sdk

Usage

// JavaScript
const { Provider } = require("xcm-sdk")

// TypeScript
import { Provider } from "xcm-sdk"

Provider

const provider = new Provider(rpc, sender)

Examples

If you want to sign with Alice in a local node:

import { Keyring } from '@polkadot/keyring'
import { cryptoWaitReady } from '@polkadot/util-crypto'

const rpc = "ws://127.0.0.1:37345" // local node ws
await cryptoWaitReady();

const keyring = new Keyring({ type: "sr25519" });
const sender = keyring.addFromUri("//Alice");

const provider = new Provider(rpc, sender);

If you want to sign with mnemonic

import { Keyring } from '@polkadot/keyring'

const sender = keyring.addFromMnemonic(
"<your mnemonic seed here>"
);

If you want to sign with polkadotjs extension

import { web3FromAddress, web3Accounts, web3Enable } from "@polkadot/extension-dapp";

const extensions = await web3Enable("<your app name>");
const accounts = await web3Accounts();
const accountId = accounts[0].address;

const injector = await web3FromAddress(accountId);

const provider = new Provider(rpc, accountId);
provider.setInjectorSigner(injector.signer);

Supported Methods

Reserve Asset Transfer with reserveTransferAsset and LimitedReserveTransferAsset methods and Asset teleportation with teleportAsset and LimitedTeleportAsset methods.

provider.limitedReserveTransferAssets(params)

provider.reserveTransferAssets(params)

provider.limitedReserveTransferAssets(params)

provider.reserveTransferAssets(params)

Methods parameters

Disclaimer

Depends on the parachain or relay chain configuration you have to use Asset teleportation or reserve asset transfer. Make sure you know what method use before execute any transfer. You can search in any scan to know, for example rococo scan

Rococo examples

If you want to tests in Testnet, you have Rococo. Get some assets: Rococo faucet

Config

The examples are in ./examples/rococo/, you can put your configuration in ./examples/rococo/rococo-examples-util.ts. Then you can run a command for each example. If you want to run them manually, you must create your own script (.js or ts) and import the dependencies.

export const rococoExampleUtils = {
  rococoRpc: 'wss://rococo-rpc.polkadot.io',
  rockMineRpc: 'wss://rococo-rockmine-rpc.polkadot.io',
  rockMineParachainId: 1000,
  mangataParachainId: 2110,
  daliParachainId: 2087,
  senderMnemonic: '<your account mnemonic>',
  rockmineDestinationAccount: '<rockmine address account>',
  daliDestinationAccount: '<dali destination account>',
  rococoDestinationAccount: '<rococo address account>',
  mangataDestinationAccount: '<mangata address account>',
  rocAmount: <amount to transfer>,
}

Send Asset from Rococo to Rockmine

command:

npx ts-node src/examples/rococo/rococo-to-rockmine.ts

manually:

  const destination = "Parachain"
  const destinationValue = 2000 // Rockmine parchain id
  const beneficiary = "AccountId32"
  const beneficiaryValue = "<rockmine account address>" // account address
  const amount = 1000000000000000

  const res = await provider.limitedTeleportAssets({
    destination,
    destinationValue,
    beneficiary,
    beneficiaryValue,
    amount,
  });

or

command:

npx ts-node src/examples/rococo/rococo-to-rockmine-no-limited.ts

manually:

  const destination = "Parachain"
  const destinationValue = 2000 // Rockmine parchain id
  const beneficiary = "AccountId32"
  const beneficiaryValue = "<rockmine account address>" // account address
  const amount = 1000000000000000

  const res = await provider.teleportAssets({
    destination,
    destinationValue,
    beneficiary,
    beneficiaryValue,
    amount,
  });

Send Asset from RockMine to Rococo

command:

npx ts-node src/examples/rococo/rockmine-to-rococo.ts

manually:

  const destinationParents = 1; // Destination to Rococo
  const beneficiary = "AccountId32"
  const beneficiaryValue = "<rococo account address>" // account address
  const amount = 1000000000000000


  const res = await provider.limitedTeleportAssets({
    destination,
    destinationValue,
    beneficiary,
    beneficiaryValue,
    amount,
  });

Send Asset from Rococo to Mangata

The ROC asset in Mangata is the asset with id 4. You can check here, in "SELECTED STATE QUERY" select tokens, then in u128 input put 4.

command:

npx ts-node src/examples/rococo/rococo-to-mangata-no-limited.ts

manually:

  const destination = "Parachain"
  const destinationValue = 2110 // Mangata parchain id
  const beneficiary = "AccountId32"
  const beneficiaryValue = "<mangata account address>" // account address
  const amount = 1000000000000000

  const res = await provider.reserveTransferAssets({
    destination,
    destinationValue,
    beneficiary,
    beneficiaryValue,
    amount,
  });

see token transfered: npm.io

Other examples

local network examples

Support for other pallets and methods

The sdk also has a method to make custom extrinsics defined by the user. You can call any pallet and method and passing a custom body to that method on your own.

provider.customExtrinsic(params)

Examples

Teleport asset

From Rococo to Rockmine using body as an object:

command:

npx ts-node src/examples/custom-extrinsic/teleport-relaychain-to-parachain.ts

manually:

const pallet = "xcmPallet"
const method = "limitedTeleportAssets"
const body = {
    dest: {
      V1: {
        parents: 0,
        interior: {
          X1: {
            Parachain: 1000,
          },
        },
      },
    },
    beneficiary: {
      V1: {
        parents: 0,
        interior: {
          X1: {
            AccountId32: {
              network: 'Any',
              id: u8aToHex(decodeAddress("<rockmine address account>")),
            },
          },
        },
      },
    },
    assets: {
      V1: [
        {
          id: {
            Concrete: {
              parents: 0,
              interior: 'Here',
            },
          },
          fun: {
            Fungible: 100000000000,
          },
        },
      ],
    },
    feeAssetItem: 0,
    weightLimit: 'Unlimited',
  }

const res = await provider.customExtrinsic({
    pallet,
    method,
    body,
})

From Rococo to Rockmine using body as an array:

const pallet = "xcmPallet"
const method = "limitedTeleportAssets"
const body = [
    // dest
    {
      V1: {
        parents: 0,
        interior: {
          X1: {
            Parachain: 1000,
          },
        },
      },
    },

    // beneficiary
    {
      V1: {
        parents: 0,
        interior: {
          X1: {
            AccountId32: {
              network: 'Any',
              id: u8aToHex(decodeAddress("<rockmine address account>")),
            },
          },
        },
      },
    },

    // assets
    {
      V1: [
        {
          id: {
            Concrete: {
              parents: 0,
              interior: 'Here',
            },
          },
          fun: {
            Fungible: 100000000000,
          },
        },
      ],
    },

    // feeAssetItem
    0,

    // weigthLimit
    'Unlimited',
  ]

const res = await provider.customExtrinsic({
    pallet,
    method,
    body,
})

From Rockmine to Rococo:

command:

npx ts-node src/examples/custom-extrinsic/teleport-parachain-to-relay.ts

manually:

const pallet = 'xcmPallet'
const method = 'limitedTeleportAssets'
const body = {
    dest: {
      V1: {
        parents: 1,
        interior: 'Here',
      },
    },
    beneficiary: {
      V1: {
        parents: 0,
        interior: {
          X1: {
            AccountId32: {
              network: 'Any',
              id: u8aToHex(decodeAddress('<rococo address account>')),
            },
          },
        },
      },
    },
    assets: {
      V1: [
        {
          id: {
            Concrete: {
              parents: 1,
              interior: 'Here',
            },
          },
          fun: {
            Fungible: 100000000000,
          },
        },
      ],
    },
    feeAssetItem: 0,
    weightLimit: 'Unlimited',
  }

  const res = await provider.customExtrinsic({
    pallet,
    method,
    body,
  })

Asset Multilocation

From this local network example, to set an asset on trappist as multilocation:

command:

npx ts-node src/examples/custom-extrinsic/mark-asset-as-multilocation.ts

manually:

const pallet = "assetRegistry"
const method = "registerReserveAsset"
const body = {
  assetId: 1, // local asset id
  assetMultiLocation: {
    parents: 1,
    interior: {
      X3: [
        {
          Parachain: 1000,
        },
        {
          PalletInstance: 50,
        },
        {
          GeneralIndex: 1,
        },
      ],
    },
  },
}

const res = await provider.customExtrinsic({
  asSudo: true,
  pallet,
  method,
  body,
})

CLI Usage

xcm sdk is also a command-line interface tool that helps you to transfer and teleport assets between chains.

install:

npm i -g xcm-sdk

There are 4 commands availables:

xcm-sdk limitedReserveTransferAssets [..args]
xcm-sdk reserveTransferAssets [..args]
xcm-sdk teleportAssets [...args]
xcm-sdk limitedTeleportAssets [..args]

commands:

npm.io

args:

CLI examples

See cli examples

Testing

Running the unit tests.

npm run test

Running the test coverage.

npm run test:cov

Change Log

See Changelog for more information.

Contributing

Contributions welcome! See Contributing.

Collaborators

License

Licensed under the MIT - see the LICENSE file for details.