difftreelog
refactor use playgrounds in unique xcm tests
in: master
1 file changed
tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth1// 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 {Keyring} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import {submitTransactionAsync} from '../substrate/substrate-api';20import {getGenericResult, generateKeyringPair, waitEvent, bigIntToDecimals} from '../deprecated-helpers/helpers';21import {MultiLocation} from '@polkadot/types/interfaces';22import {blake2AsHex} from '@polkadot/util-crypto';23import getBalance from '../substrate/get-balance';24import {XcmV2TraitsError, XcmV2TraitsOutcome} from '../interfaces';25import {itSub, expect, describeXcm, usingPlaygrounds} from '../util/playgrounds';2627const UNIQUE_CHAIN = 2037;28const ACALA_CHAIN = 2000;29const MOONBEAM_CHAIN = 2004;3031const RELAY_PORT = 9844;32const ACALA_PORT = 9946;33const MOONBEAM_PORT = 9947;3435const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT;36const acalaUrl = 'ws://127.0.0.1:' + ACALA_PORT;37const moonbeamUrl = 'ws://127.0.0.1:' + MOONBEAM_PORT;3839const ACALA_DECIMALS = 12;4041const TRANSFER_AMOUNT = 2000000000000000000000000n;4243describeXcm('[XCM] Integration test: Exchanging tokens with Acala', () => {44 let alice: IKeyringPair;45 let randomAccount: IKeyringPair;4647 let balanceUniqueTokenInit: bigint;48 let balanceUniqueTokenMiddle: bigint;49 let balanceUniqueTokenFinal: bigint;50 let balanceAcalaTokenInit: bigint;51 let balanceAcalaTokenMiddle: bigint;52 let balanceAcalaTokenFinal: bigint;53 let balanceUniqueForeignTokenInit: bigint;54 let balanceUniqueForeignTokenMiddle: bigint;55 let balanceUniqueForeignTokenFinal: bigint;5657 before(async () => {58 await usingPlaygrounds(async (_helper, privateKey) => {59 const keyringSr25519 = new Keyring({type: 'sr25519'});6061 alice = privateKey('//Alice');62 randomAccount = generateKeyringPair(keyringSr25519);63 });6465 // Acala side66 await usingPlaygrounds.atUrl(acalaUrl, async (helper) => {67 const destination = {68 V0: {69 X2: [70 'Parent',71 {72 Parachain: UNIQUE_CHAIN,73 },74 ],75 },76 };7778 const metadata = {79 name: 'UNQ',80 symbol: 'UNQ',81 decimals: 18,82 minimalBalance: 1,83 };8485 // TODO86 const tx = helper.getApi().tx.assetRegistry.registerForeignAsset(destination, metadata);87 const sudoTx = helper.getApi().tx.sudo.sudo(tx as any);88 const events = await submitTransactionAsync(alice, sudoTx);89 const result = getGenericResult(events);90 expect(result.success).to.be.true;9192 // const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n);93 // const events1 = await submitTransactionAsync(alice, tx1);94 // const result1 = getGenericResult(events1);95 // expect(result1.success).to.be.true;96 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);9798 // [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]);99 balanceAcalaTokenInit = await helper.balance.getSubstrate(randomAccount.address);100 {101 // TODO102 const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;103 balanceUniqueForeignTokenInit = BigInt(free);104 }105 });106107 // Unique side108 await usingPlaygrounds(async (helper) => {109 // const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT);110 // const events0 = await submitTransactionAsync(alice, tx0);111 // const result0 = getGenericResult(events0);112 // expect(result0.success).to.be.true;113 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT);114115 // [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]);116 balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);117 });118 });119120 itSub('Should connect and send UNQ to Acala', async ({helper}) => {121122 // Unique side123 const destination = {124 V0: {125 X2: [126 'Parent',127 {128 Parachain: ACALA_CHAIN,129 },130 ],131 },132 };133134 const beneficiary = {135 V0: {136 X1: {137 AccountId32: {138 network: 'Any',139 id: randomAccount.addressRaw,140 },141 },142 },143 };144145 const assets = {146 V1: [147 {148 id: {149 Concrete: {150 parents: 0,151 interior: 'Here',152 },153 },154 fun: {155 Fungible: TRANSFER_AMOUNT,156 },157 },158 ],159 };160161 const feeAssetItem = 0;162163 const weightLimit = {164 Limited: 5000000000,165 };166167 // TODO168 const tx = helper.getApi().tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);169 const events = await submitTransactionAsync(randomAccount, tx);170 const result = getGenericResult(events);171 expect(result.success).to.be.true;172173 // [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]);174 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);175176 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;177 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));178 expect(unqFees > 0n).to.be.true;179180 // Acala side181 await usingPlaygrounds.atUrl(acalaUrl, async (helper) => {182 // await waitNewBlocks(api, 3);183 await helper.wait.newBlocks(3);184185 // TODO186 const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;187 balanceUniqueForeignTokenMiddle = BigInt(free);188189 // [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]);190 balanceAcalaTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);191192 const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle;193 const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit;194195 console.log(196 '[Unique -> Acala] transaction fees on Acala: %s ACA',197 bigIntToDecimals(acaFees, ACALA_DECIMALS),198 );199 console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer));200 expect(acaFees == 0n).to.be.true;201 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;202 });203 });204205 itSub('Should connect to Acala and send UNQ back', async ({helper}) => {206207 // Acala side208 await usingPlaygrounds.atUrl(acalaUrl, async (helper) => {209 const destination = {210 V1: {211 parents: 1,212 interior: {213 X2: [214 {Parachain: UNIQUE_CHAIN},215 {216 AccountId32: {217 network: 'Any',218 id: randomAccount.addressRaw,219 },220 },221 ],222 },223 },224 };225226 const id = {227 ForeignAsset: 0,228 };229230 const destWeight = 50000000;231232 // TODO233 const tx = helper.getApi().tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight);234 const events = await submitTransactionAsync(randomAccount, tx);235 const result = getGenericResult(events);236 expect(result.success).to.be.true;237238 // [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]);239 balanceAcalaTokenFinal = await helper.balance.getSubstrate(randomAccount.address);240 {241 // TODO242 const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any;243 balanceUniqueForeignTokenFinal = BigInt(free);244 }245246 const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal;247 const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal;248249 console.log(250 '[Acala -> Unique] transaction fees on Acala: %s ACA',251 bigIntToDecimals(acaFees, ACALA_DECIMALS),252 );253 console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer));254255 expect(acaFees > 0).to.be.true;256 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;257 });258259 // await waitNewBlocks(api, 3);260 await helper.wait.newBlocks(3);261262 // [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]);263 balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccount.address);264 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;265 expect(actuallyDelivered > 0).to.be.true;266267 console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered));268269 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;270 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));271 expect(unqFees == 0n).to.be.true;272 });273});274275// These tests are relevant only when the foreign asset pallet is disabled276describeXcm('[XCM] Integration test: Unique rejects non-native tokens', () => {277 let alice: IKeyringPair;278279 before(async () => {280 await usingPlaygrounds(async (_helper, privateKey) => {281 alice = privateKey('//Alice');282 });283 });284285 itSub('Unique rejects tokens from the Relay', async ({helper}) => {286 await usingPlaygrounds.atUrl(relayUrl, async (helper) => {287 const destination = {288 V1: {289 parents: 0,290 interior: {X1: {291 Parachain: UNIQUE_CHAIN,292 },293 },294 }};295296 const beneficiary = {297 V1: {298 parents: 0,299 interior: {X1: {300 AccountId32: {301 network: 'Any',302 id: alice.addressRaw,303 },304 }},305 },306 };307308 const assets = {309 V1: [310 {311 id: {312 Concrete: {313 parents: 0,314 interior: 'Here',315 },316 },317 fun: {318 Fungible: 50_000_000_000_000_000n,319 },320 },321 ],322 };323324 const feeAssetItem = 0;325326 const weightLimit = {327 Limited: 5_000_000_000,328 };329330 // TODO331 const tx = helper.getApi().tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);332 const events = await submitTransactionAsync(alice, tx);333 const result = getGenericResult(events);334 expect(result.success).to.be.true;335 });336337 const maxWaitBlocks = 3;338339 // TODO340 const dmpQueueExecutedDownward = await waitEvent(341 helper.getApi(),342 maxWaitBlocks,343 'dmpQueue',344 'ExecutedDownward',345 );346347 expect(348 dmpQueueExecutedDownward != null,349 '[Relay] dmpQueue.ExecutedDownward event is expected',350 ).to.be.true;351352 const event = dmpQueueExecutedDownward!.event;353 const outcome = event.data[1] as XcmV2TraitsOutcome;354355 expect(356 outcome.isIncomplete,357 '[Relay] The outcome of the XCM should be `Incomplete`',358 ).to.be.true;359360 const incomplete = outcome.asIncomplete;361 expect(362 incomplete[1].toString() == 'AssetNotFound',363 '[Relay] The XCM error should be `AssetNotFound`',364 ).to.be.true;365 });366367 itSub('Unique rejects ACA tokens from Acala', async ({helper}) => {368 await usingPlaygrounds.atUrl(acalaUrl, async (helper) => {369 const destination = {370 V1: {371 parents: 1,372 interior: {373 X2: [374 {Parachain: UNIQUE_CHAIN},375 {376 AccountId32: {377 network: 'Any',378 id: alice.addressRaw,379 },380 },381 ],382 },383 },384 };385386 const id = {387 Token: 'ACA',388 };389390 const destWeight = 50000000;391392 // TODO393 const tx = helper.getApi().tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight);394 const events = await submitTransactionAsync(alice, tx);395 const result = getGenericResult(events);396 expect(result.success).to.be.true;397 });398399 const maxWaitBlocks = 3;400401 // TODO402 const xcmpQueueFailEvent = await waitEvent(helper.getApi(), maxWaitBlocks, 'xcmpQueue', 'Fail');403404 expect(405 xcmpQueueFailEvent != null,406 '[Acala] xcmpQueue.FailEvent event is expected',407 ).to.be.true;408409 const event = xcmpQueueFailEvent!.event;410 const outcome = event.data[1] as XcmV2TraitsError;411412 expect(413 outcome.isUntrustedReserveLocation,414 '[Acala] The XCM error should be `UntrustedReserveLocation`',415 ).to.be.true;416 });417});418419describeXcm('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => {420421 // Unique constants422 let uniqueAlice: IKeyringPair;423 let uniqueAssetLocation;424425 let randomAccountUnique: IKeyringPair;426 let randomAccountMoonbeam: IKeyringPair;427428 // Moonbeam constants429 let assetId: string;430431 const moonbeamKeyring = new Keyring({type: 'ethereum'});432 const alithPrivateKey = '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133';433 const baltatharPrivateKey = '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b';434 const dorothyPrivateKey = '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68';435436 const alithAccount = moonbeamKeyring.addFromUri(alithPrivateKey, undefined, 'ethereum');437 const baltatharAccount = moonbeamKeyring.addFromUri(baltatharPrivateKey, undefined, 'ethereum');438 const dorothyAccount = moonbeamKeyring.addFromUri(dorothyPrivateKey, undefined, 'ethereum');439440 const councilVotingThreshold = 2;441 const technicalCommitteeThreshold = 2;442 const votingPeriod = 3;443 const delayPeriod = 0;444445 const uniqueAssetMetadata = {446 name: 'xcUnique',447 symbol: 'xcUNQ',448 decimals: 18,449 isFrozen: false,450 minimalBalance: 1,451 };452453 let balanceUniqueTokenInit: bigint;454 let balanceUniqueTokenMiddle: bigint;455 let balanceUniqueTokenFinal: bigint;456 let balanceForeignUnqTokenInit: bigint;457 let balanceForeignUnqTokenMiddle: bigint;458 let balanceForeignUnqTokenFinal: bigint;459 let balanceGlmrTokenInit: bigint;460 let balanceGlmrTokenMiddle: bigint;461 let balanceGlmrTokenFinal: bigint;462463 before(async () => {464 await usingPlaygrounds(async (_helper, privateKey) => {465 const keyringEth = new Keyring({type: 'ethereum'});466 const keyringSr25519 = new Keyring({type: 'sr25519'});467468 uniqueAlice = privateKey('//Alice');469 randomAccountUnique = generateKeyringPair(keyringSr25519);470 randomAccountMoonbeam = generateKeyringPair(keyringEth);471472 balanceForeignUnqTokenInit = 0n;473 });474475 await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => {476 // TODO477478 const api = helper.getApi();479480 // >>> Sponsoring Dorothy >>>481 console.log('Sponsoring Dorothy.......');482 // const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n);483 // const events0 = await submitTransactionAsync(alithAccount, tx0);484 // const result0 = getGenericResult(events0);485 // expect(result0.success).to.be.true;486 await helper.balance.transferToSubstrate(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n);487 console.log('Sponsoring Dorothy.......DONE');488 // <<< Sponsoring Dorothy <<<489490 const sourceLocation: MultiLocation = api.createType(491 'MultiLocation',492 {493 parents: 1,494 interior: {X1: {Parachain: UNIQUE_CHAIN}},495 },496 );497498 uniqueAssetLocation = {XCM: sourceLocation};499 const existentialDeposit = 1;500 const isSufficient = true;501 const unitsPerSecond = '1';502 const numAssetsWeightHint = 0;503504 const registerTx = api.tx.assetManager.registerForeignAsset(505 uniqueAssetLocation,506 uniqueAssetMetadata,507 existentialDeposit,508 isSufficient,509 );510 console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || '');511512 const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond(513 uniqueAssetLocation,514 unitsPerSecond,515 numAssetsWeightHint,516 );517 console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || '');518519 const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]);520 console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || '');521522 // >>> Note motion preimage >>>523 console.log('Note motion preimage.......');524 const encodedProposal = batchCall?.method.toHex() || '';525 const proposalHash = blake2AsHex(encodedProposal);526 console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal);527 console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash);528 console.log('Encoded length %d', encodedProposal.length);529530 const tx1 = api.tx.democracy.notePreimage(encodedProposal);531 const events1 = await submitTransactionAsync(baltatharAccount, tx1);532 const result1 = getGenericResult(events1);533 expect(result1.success).to.be.true;534 console.log('Note motion preimage.......DONE');535 // <<< Note motion preimage <<<536537 // >>> Propose external motion through council >>>538 console.log('Propose external motion through council.......');539 const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash);540 const tx2 = api.tx.councilCollective.propose(541 councilVotingThreshold,542 externalMotion,543 externalMotion.encodedLength,544 );545 const events2 = await submitTransactionAsync(baltatharAccount, tx2);546 const result2 = getGenericResult(events2);547 expect(result2.success).to.be.true;548549 const encodedMotion = externalMotion?.method.toHex() || '';550 const motionHash = blake2AsHex(encodedMotion);551 console.log('Motion hash is %s', motionHash);552553 const tx3 = api.tx.councilCollective.vote(motionHash, 0, true);554 {555 const events3 = await submitTransactionAsync(dorothyAccount, tx3);556 const result3 = getGenericResult(events3);557 expect(result3.success).to.be.true;558 }559 {560 const events3 = await submitTransactionAsync(baltatharAccount, tx3);561 const result3 = getGenericResult(events3);562 expect(result3.success).to.be.true;563 }564565 const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength);566 const events4 = await submitTransactionAsync(dorothyAccount, tx4);567 const result4 = getGenericResult(events4);568 expect(result4.success).to.be.true;569 console.log('Propose external motion through council.......DONE');570 // <<< Propose external motion through council <<<571572 // >>> Fast track proposal through technical committee >>>573 console.log('Fast track proposal through technical committee.......');574 const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod);575 const tx5 = api.tx.techCommitteeCollective.propose(576 technicalCommitteeThreshold,577 fastTrack,578 fastTrack.encodedLength,579 );580 const events5 = await submitTransactionAsync(alithAccount, tx5);581 const result5 = getGenericResult(events5);582 expect(result5.success).to.be.true;583584 const encodedFastTrack = fastTrack?.method.toHex() || '';585 const fastTrackHash = blake2AsHex(encodedFastTrack);586 console.log('FastTrack hash is %s', fastTrackHash);587588 const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1;589 const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true);590 {591 const events6 = await submitTransactionAsync(baltatharAccount, tx6);592 const result6 = getGenericResult(events6);593 expect(result6.success).to.be.true;594 }595 {596 const events6 = await submitTransactionAsync(alithAccount, tx6);597 const result6 = getGenericResult(events6);598 expect(result6.success).to.be.true;599 }600601 const tx7 = api.tx.techCommitteeCollective602 .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength);603 const events7 = await submitTransactionAsync(baltatharAccount, tx7);604 const result7 = getGenericResult(events7);605 expect(result7.success).to.be.true;606 console.log('Fast track proposal through technical committee.......DONE');607 // <<< Fast track proposal through technical committee <<<608609 // >>> Referendum voting >>>610 console.log('Referendum voting.......');611 const tx8 = api.tx.democracy.vote(612 0,613 {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}},614 );615 const events8 = await submitTransactionAsync(dorothyAccount, tx8);616 const result8 = getGenericResult(events8);617 expect(result8.success).to.be.true;618 console.log('Referendum voting.......DONE');619 // <<< Referendum voting <<<620621 // >>> Acquire Unique AssetId Info on Moonbeam >>>622 console.log('Acquire Unique AssetId Info on Moonbeam.......');623624 // Wait for the democracy execute625 // await waitNewBlocks(api, 5);626 await helper.wait.newBlocks(5);627628 assetId = (await api.query.assetManager.assetTypeId({629 XCM: sourceLocation,630 })).toString();631632 console.log('UNQ asset ID is %s', assetId);633 console.log('Acquire Unique AssetId Info on Moonbeam.......DONE');634 // >>> Acquire Unique AssetId Info on Moonbeam >>>635636 // >>> Sponsoring random Account >>>637 console.log('Sponsoring random Account.......');638 // const tx10 = api.tx.balances.transfer(randomAccountMoonbeam.address, 11_000_000_000_000_000_000n);639 // const events10 = await submitTransactionAsync(baltatharAccount, tx10);640 // const result10 = getGenericResult(events10);641 // expect(result10.success).to.be.true;642 await helper.balance.transferToSubstrate(baltatharAccount, randomAccountMoonbeam.address, 11_000_000_000_000_000_000n);643 console.log('Sponsoring random Account.......DONE');644 // <<< Sponsoring random Account <<<645646 [balanceGlmrTokenInit] = await getBalance(api, [randomAccountMoonbeam.address]);647 });648649 await usingPlaygrounds(async (helper) => {650 // const tx0 = api.tx.balances.transfer(randomAccountUnique.address, 10n * TRANSFER_AMOUNT);651 // const events0 = await submitTransactionAsync(uniqueAlice, tx0);652 // const result0 = getGenericResult(events0);653 // expect(result0.success).to.be.true;654 await helper.balance.transferToSubstrate(uniqueAlice, randomAccountUnique.address, 10n * TRANSFER_AMOUNT);655656 // [balanceUniqueTokenInit] = await getBalance(api, [randomAccountUnique.address]);657 balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccountUnique.address);658 });659 });660661 itSub('Should connect and send UNQ to Moonbeam', async ({helper}) => {662 const currencyId = {663 NativeAssetId: 'Here',664 };665 const dest = {666 V1: {667 parents: 1,668 interior: {669 X2: [670 {Parachain: MOONBEAM_CHAIN},671 {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}},672 ],673 },674 },675 };676 const amount = TRANSFER_AMOUNT;677 const destWeight = 850000000;678679 // TODO680 const tx = helper.getApi().tx.xTokens.transfer(currencyId, amount, dest, destWeight);681 const events = await submitTransactionAsync(randomAccountUnique, tx);682 const result = getGenericResult(events);683 expect(result.success).to.be.true;684685 // [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccountUnique.address]);686 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccountUnique.address);687 expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true;688689 const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;690 console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', bigIntToDecimals(transactionFees));691 expect(transactionFees > 0).to.be.true;692693 await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => {694 // await waitNewBlocks(api, 3);695 await helper.wait.newBlocks(3);696697 // [balanceGlmrTokenMiddle] = await getBalance(api, [randomAccountMoonbeam.address]);698 balanceGlmrTokenMiddle = await helper.balance.getSubstrate(randomAccountMoonbeam.address);699700 const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle;701 console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees));702 expect(glmrFees == 0n).to.be.true;703704 // TODO705 const unqRandomAccountAsset = (706 await helper.getApi().query.assets.account(assetId, randomAccountMoonbeam.address)707 ).toJSON()! as any;708709 balanceForeignUnqTokenMiddle = BigInt(unqRandomAccountAsset['balance']);710 const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit;711 console.log('[Unique -> Moonbeam] income %s UNQ', bigIntToDecimals(unqIncomeTransfer));712 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;713 });714 });715716 itSub('Should connect to Moonbeam and send UNQ back', async ({helper}) => {717 await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => {718 const asset = {719 V1: {720 id: {721 Concrete: {722 parents: 1,723 interior: {724 X1: {Parachain: UNIQUE_CHAIN},725 },726 },727 },728 fun: {729 Fungible: TRANSFER_AMOUNT,730 },731 },732 };733 const destination = {734 V1: {735 parents: 1,736 interior: {737 X2: [738 {Parachain: UNIQUE_CHAIN},739 {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}},740 ],741 },742 },743 };744 const destWeight = 50000000;745746 // TODO747 const tx = helper.getApi().tx.xTokens.transferMultiasset(asset, destination, destWeight);748 const events = await submitTransactionAsync(randomAccountMoonbeam, tx);749 const result = getGenericResult(events);750 expect(result.success).to.be.true;751752 // [balanceGlmrTokenFinal] = await getBalance(api, [randomAccountMoonbeam.address]);753 balanceGlmrTokenFinal = await helper.balance.getSubstrate(randomAccountMoonbeam.address);754755 const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal;756 console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees));757 expect(glmrFees > 0).to.be.true;758759 // TODO760 const unqRandomAccountAsset = (761 await helper.getApi().query.assets.account(assetId, randomAccountMoonbeam.address)762 ).toJSON()! as any;763764 expect(unqRandomAccountAsset).to.be.null;765766 balanceForeignUnqTokenFinal = 0n;767768 const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal;769 console.log('[Unique -> Moonbeam] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer));770 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;771 });772773 // await waitNewBlocks(api, 3);774 await helper.wait.newBlocks(3);775776 // [balanceUniqueTokenFinal] = await getBalance(api, [randomAccountUnique.address]);777 balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccountUnique.address);778 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;779 expect(actuallyDelivered > 0).to.be.true;780781 console.log('[Moonbeam -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered));782783 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;784 console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees));785 expect(unqFees == 0n).to.be.true;786 });787});