git.delta.rocks / unique-network / refs/commits / a478235c0b6e

difftreelog

source

js-packages/tests/xcm/lowLevelXcmQuartz.test.ts10.9 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import type {IKeyringPair} from '@polkadot/types/types';18import {itSub, describeXCM, usingPlaygrounds, usingKaruraPlaygrounds,  usingMoonriverPlaygrounds, usingShidenPlaygrounds, usingRelayPlaygrounds} from '../util/index.js';19import {QUARTZ_CHAIN,  QTZ_DECIMALS,  SHIDEN_DECIMALS, karuraUrl, moonriverUrl,  shidenUrl,  SAFE_XCM_VERSION, XcmTestHelper, TRANSFER_AMOUNT, SENDER_BUDGET, relayUrl} from './xcm.types.js';20import {hexToString} from '@polkadot/util';2122const testHelper = new XcmTestHelper('quartz');2324describeXCM('[XCMLL] Integration test: Exchanging tokens with Karura', () => {25  let alice: IKeyringPair;26  let randomAccount: IKeyringPair;2728  before(async () => {29    await usingPlaygrounds(async (helper, privateKey) => {30      alice = await privateKey('//Alice');31      [randomAccount] = await helper.arrange.createAccounts([0n], alice);3233      // Set the default version to wrap the first message to other chains.34      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);35    });3637    await usingKaruraPlaygrounds(karuraUrl, async (helper) => {38      const destination = {39        V2: {40          parents: 1,41          interior: {42            X1: {43              Parachain: QUARTZ_CHAIN,44            },45          },46        },47      };4849      const metadata = {50        name: 'Quartz',51        symbol: 'QTZ',52        decimals: 18,53        minimalBalance: 1000000000000000000n,54      };5556      const assets = (await (helper.callRpc('api.query.assetRegistry.assetMetadatas.entries'))).map(([_k, v]: [any, any]) =>57        hexToString(v.toJSON()['symbol'])) as string[];5859      if(!assets.includes('QTZ')) {60        await helper.getSudo().assetRegistry.registerForeignAsset(alice, destination, metadata);61      } else {62        console.log('QTZ token already registered on Karura assetRegistry pallet');63      }64      await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);65    });6667    await usingPlaygrounds(async (helper) => {68      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);69    });70  });7172  itSub('Should connect and send QTZ to Karura', async () => {73    await testHelper.sendUnqTo('karura', randomAccount);74  });7576  itSub('Should connect to Karura and send QTZ back', async () => {77    await testHelper.sendUnqBack('karura', alice, randomAccount);78  });7980  itSub('Karura can send only up to its balance', async () => {81    await testHelper.sendOnlyOwnedBalance('karura', alice);82  });83});84// These tests are relevant only when85// the the corresponding foreign assets are not registered86describeXCM('[XCMLL] Integration test: Quartz rejects non-native tokens', () => {87  let alice: IKeyringPair;888990  before(async () => {91    await usingPlaygrounds(async (helper, privateKey) => {92      alice = await privateKey('//Alice');93949596      // Set the default version to wrap the first message to other chains.97      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);98    });99  });100101  itSub('Quartz rejects KAR tokens from Karura', async () => {102    await testHelper.rejectNativeTokensFrom('karura', alice);103  });104105  itSub('Quartz rejects MOVR tokens from Moonriver', async () => {106    await testHelper.rejectNativeTokensFrom('moonriver', alice);107  });108109  itSub('Quartz rejects SDN tokens from Shiden', async () => {110    await testHelper.rejectNativeTokensFrom('shiden', alice);111  });112});113114describeXCM('[XCMLL] Integration test: Exchanging QTZ with Moonriver', () => {115  // Quartz constants116  let alice: IKeyringPair;117  let quartzAssetLocation;118119  let randomAccountQuartz: IKeyringPair;120  let randomAccountMoonriver: IKeyringPair;121122  // Moonriver constants123  let assetId: string;124125  const quartzAssetMetadata = {126    name: 'xcQuartz',127    symbol: 'xcQTZ',128    decimals: 18,129    isFrozen: false,130    minimalBalance: 1n,131  };132133134  before(async () => {135    await usingPlaygrounds(async (helper, privateKey) => {136      alice = await privateKey('//Alice');137      [randomAccountQuartz] = await helper.arrange.createAccounts([0n], alice);138139140      // Set the default version to wrap the first message to other chains.141      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);142    });143144    await usingMoonriverPlaygrounds(moonriverUrl, async (helper) => {145      const alithAccount = helper.account.alithAccount();146      const baltatharAccount = helper.account.baltatharAccount();147      const dorothyAccount = helper.account.dorothyAccount();148149      randomAccountMoonriver = helper.account.create();150151      // >>> Sponsoring Dorothy >>>152      console.log('Sponsoring Dorothy.......');153      await helper.balance.transferToEthereum(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);154      console.log('Sponsoring Dorothy.......DONE');155      // <<< Sponsoring Dorothy <<<156157      quartzAssetLocation = {158        XCM: {159          parents: 1,160          interior: {X1: {Parachain: QUARTZ_CHAIN}},161        },162      };163      const existentialDeposit = 1n;164      const isSufficient = true;165      const unitsPerSecond = 1n;166      const numAssetsWeightHint = 0;167      if((await helper.assetManager.assetTypeId(quartzAssetLocation)).toJSON()) {168        console.log('Quartz asset already registered on Moonriver');169      } else {170        const encodedProposal = helper.assetManager.makeRegisterForeignAssetProposal({171          location: quartzAssetLocation,172          metadata: quartzAssetMetadata,173          existentialDeposit,174          isSufficient,175          unitsPerSecond,176          numAssetsWeightHint,177        });178179        console.log('Encoded proposal for registerForeignAsset & setAssetUnitsPerSecond is %s', encodedProposal);180181        await helper.fastDemocracy.executeProposal('register QTZ foreign asset', encodedProposal);182      }183      // >>> Acquire Quartz AssetId Info on Moonriver >>>184      console.log('Acquire Quartz AssetId Info on Moonriver.......');185186      assetId = (await helper.assetManager.assetTypeId(quartzAssetLocation)).toString();187188      console.log('QTZ asset ID is %s', assetId);189      console.log('Acquire Quartz AssetId Info on Moonriver.......DONE');190      // >>> Acquire Quartz AssetId Info on Moonriver >>>191192      // >>> Sponsoring random Account >>>193      console.log('Sponsoring random Account.......');194      await helper.balance.transferToEthereum(baltatharAccount, randomAccountMoonriver.address, 11_000_000_000_000_000_000n);195      console.log('Sponsoring random Account.......DONE');196      // <<< Sponsoring random Account <<<197    });198199    await usingPlaygrounds(async (helper) => {200      await helper.balance.transferToSubstrate(alice, randomAccountQuartz.address, 10n * TRANSFER_AMOUNT);201    });202  });203204  itSub('Should connect and send QTZ to Moonriver', async () => {205    await testHelper.sendUnqTo('moonriver', randomAccountQuartz, randomAccountMoonriver);206  });207208  itSub('Should connect to Moonriver and send QTZ back', async () => {209    await testHelper.sendUnqBack('moonriver', alice, randomAccountQuartz);210  });211212  itSub('Moonriver can send only up to its balance', async () => {213    await testHelper.sendOnlyOwnedBalance('moonriver', alice);214  });215216  itSub('Should not accept reserve transfer of QTZ from Moonriver', async () => {217    await testHelper.rejectReserveTransferUNQfrom('moonriver', alice);218  });219});220221describeXCM('[XCMLL] Integration test: Exchanging tokens with Shiden', () => {222  let alice: IKeyringPair;223  let randomAccount: IKeyringPair;224225  const QTZ_ASSET_ID_ON_SHIDEN = 18_446_744_073_709_551_633n; // The value is taken from the live Shiden226  const QTZ_MINIMAL_BALANCE_ON_SHIDEN = 1n; // The value is taken from the live Shiden227228  // Quartz -> Shiden229  const shidenInitialBalance = 1n * (10n ** SHIDEN_DECIMALS); // 1 SHD, existential deposit required to actually create the account on Shiden230  const unitsPerSecond = 500_451_000_000_000_000_000n; // The value is taken from the live Shiden231232  before(async () => {233    await usingPlaygrounds(async (helper, privateKey) => {234      alice = await privateKey('//Alice');235      randomAccount = helper.arrange.createEmptyAccount();236      await helper.balance.transferToSubstrate(alice, randomAccount.address, SENDER_BUDGET);237      console.log('sender: ', randomAccount.address);238239      // Set the default version to wrap the first message to other chains.240      await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);241    });242243    await usingShidenPlaygrounds(shidenUrl, async (helper) => {244      if(!(await helper.callRpc('api.query.assets.asset', [QTZ_ASSET_ID_ON_SHIDEN])).toJSON()) {245        console.log('1. Create foreign asset and metadata');246        await helper.getSudo().assets.forceCreate(247          alice,248          QTZ_ASSET_ID_ON_SHIDEN,249          alice.address,250          QTZ_MINIMAL_BALANCE_ON_SHIDEN,251        );252253        await helper.assets.setMetadata(254          alice,255          QTZ_ASSET_ID_ON_SHIDEN,256          'Quartz',257          'QTZ',258          Number(QTZ_DECIMALS),259        );260261        console.log('2. Register asset location on Shiden');262        const assetLocation = {263          V2: {264            parents: 1,265            interior: {266              X1: {267                Parachain: QUARTZ_CHAIN,268              },269            },270          },271        };272273        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.registerAssetLocation', [assetLocation, QTZ_ASSET_ID_ON_SHIDEN]);274275        console.log('3. Set QTZ payment for XCM execution on Shiden');276        await helper.getSudo().executeExtrinsic(alice, 'api.tx.xcAssetConfig.setAssetUnitsPerSecond', [assetLocation, unitsPerSecond]);277      } else {278        console.log('QTZ is already registered on Shiden');279      }280      console.log('4. Transfer 1 SDN to recipient to create the account (needed due to existential balance)');281      await helper.balance.transferToSubstrate(alice, randomAccount.address, shidenInitialBalance);282    });283  });284285  itSub('Should connect and send QTZ to Shiden', async () => {286    await testHelper.sendUnqTo('shiden', randomAccount);287  });288289  itSub('Should connect to Shiden and send QTZ back', async () => {290    await testHelper.sendUnqBack('shiden', alice, randomAccount);291  });292293  itSub('Shiden can send only up to its balance', async () => {294    await testHelper.sendOnlyOwnedBalance('shiden', alice);295  });296297  itSub('Should not accept reserve transfer of QTZ from Shiden', async () => {298    await testHelper.rejectReserveTransferUNQfrom('shiden', alice);299  });300});