difftreelog
test(xcm) unique <-> moonbeam
in: master
1 file changed
tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth17import chai from 'chai';17import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';18import chaiAsPromised from 'chai-as-promised';191920import {WsProvider} from '@polkadot/api';20import {WsProvider, Keyring} from '@polkadot/api';21import {ApiOptions} from '@polkadot/api/types';21import {ApiOptions} from '@polkadot/api/types';22import {IKeyringPair} from '@polkadot/types/types';22import {IKeyringPair} from '@polkadot/types/types';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';24import {getGenericResult, generateKeyringPair} from '../util/helpers';24import {getGenericResult, generateKeyringPair} from '../util/helpers';25import {MultiLocation} from '@polkadot/types/interfaces';26import {blake2AsHex} from '@polkadot/util-crypto';25import waitNewBlocks from '../substrate/wait-new-blocks';27import waitNewBlocks from '../substrate/wait-new-blocks';26import getBalance from '../substrate/get-balance';28import getBalance from '../substrate/get-balance';2729303231const UNIQUE_CHAIN = 2037;33const UNIQUE_CHAIN = 2037;32const ACALA_CHAIN = 2000;34const ACALA_CHAIN = 2000;35const MOONBEAM_CHAIN = 2004;333634const ACALA_PORT = '9946';37const ACALA_PORT = 9946;38const MOONBEAM_PORT = 9947;353936const TRANSFER_AMOUNT = 2000000000000000000000000n;40const TRANSFER_AMOUNT = 2000000000000000000000000n;374142function parachainApiOptions(port: number): ApiOptions {43 return {44 provider: new WsProvider('ws://127.0.0.1:' + port.toString()),45 };46}4748function acalaOptions(): ApiOptions {49 return parachainApiOptions(ACALA_PORT);50}5152function moonbeamOptions(): ApiOptions {53 return parachainApiOptions(MOONBEAM_PORT);54}5538describe('Integration test: Exchanging UNQ with Acala', () => {56describe('Integration test: Exchanging UNQ with Acala', () => {39 let alice: IKeyringPair;57 let alice: IKeyringPair;40 let randomAccount: IKeyringPair;58 let randomAccount: IKeyringPair;41 59 42 let balanceUniqueTokenBefore: bigint;60 let balanceUniqueTokenInit: bigint;43 let balanceUniqueTokenAfter: bigint;61 let balanceUniqueTokenMiddle: bigint;44 let balanceUniqueTokenFinal: bigint;62 let balanceUniqueTokenFinal: bigint;45 let balanceAcalaTokenBefore: bigint;63 let balanceAcalaTokenInit: bigint;46 let balanceAcalaTokenAfter: bigint;64 let balanceAcalaTokenMiddle: bigint;47 let balanceAcalaTokenFinal: bigint;65 let balanceAcalaTokenFinal: bigint;48 let balanceUniqueForeignTokenAfter: bigint;66 let balanceUniqueForeignTokenInit: bigint;49 let balanceUniqueForeignTokenBefore: bigint;67 let balanceUniqueForeignTokenMiddle: bigint;50 let balanceUniqueForeignTokenFinal: bigint;68 let balanceUniqueForeignTokenFinal: bigint;51 69 52 before(async () => {70 before(async () => {53 await usingApi(async (api, privateKeyWrapper) => {71 await usingApi(async (api, privateKeyWrapper) => {54 alice = privateKeyWrapper('//Alice');72 alice = privateKeyWrapper('//Alice');55 randomAccount = generateKeyringPair();73 randomAccount = generateKeyringPair();56 });74 });57 7558 const acalaApiOptions: ApiOptions = {59 provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT),60 };61 62 // Acala side76 // Acala side63 await usingApi(77 await usingApi(64 async (api) => {78 async (api) => {91 const result1 = getGenericResult(events1);105 const result1 = getGenericResult(events1);92 expect(result1.success).to.be.true;106 expect(result1.success).to.be.true;93 107 94 [balanceAcalaTokenBefore] = await getBalance(api, [randomAccount.address]);108 [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]);95 {109 {96 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;110 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;97 balanceUniqueForeignTokenBefore = BigInt(free);111 balanceUniqueForeignTokenInit = BigInt(free);98 }112 }99 },113 },100 acalaApiOptions,114 acalaOptions(),101 );115 );102 116 103 // Unique side117 // Unique side107 const result0 = getGenericResult(events0);121 const result0 = getGenericResult(events0);108 expect(result0.success).to.be.true;122 expect(result0.success).to.be.true;109 123 110 [balanceUniqueTokenBefore] = await getBalance(api, [randomAccount.address]);124 [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]);111 });125 });112 });126 });113 127 165 const result = getGenericResult(events);179 const result = getGenericResult(events);166 expect(result.success).to.be.true;180 expect(result.success).to.be.true;167 181 168 [balanceUniqueTokenAfter] = await getBalance(api, [randomAccount.address]);182 [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]);169 183 170 const unqFees = balanceUniqueTokenBefore - balanceUniqueTokenAfter;184 const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle + TRANSFER_AMOUNT;171 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', unqFees);185 console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', unqFees);172 expect(unqFees > 0n).to.be.true;186 expect(unqFees > 0n).to.be.true;173 });187 });174 188 175 // Acala side189 // Acala side176 await usingApi(190 await usingApi(177 async (api) => {191 async (api) => {178 // todo do something about instant sealing, where there might not be any new blocks179 await waitNewBlocks(api, 3);192 await waitNewBlocks(api, 3);180 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;193 const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any;181 balanceUniqueForeignTokenAfter = BigInt(free);194 balanceUniqueForeignTokenMiddle = BigInt(free);182 195 183 [balanceAcalaTokenAfter] = await getBalance(api, [randomAccount.address]);196 [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]);184197185 const acaFees = balanceAcalaTokenBefore - balanceAcalaTokenAfter;198 const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle;186 const unqDiffAfterIncomeTransfer = balanceUniqueForeignTokenAfter - balanceUniqueForeignTokenBefore;199 const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit;187200188 const unqFees = unqDiffAfterIncomeTransfer - TRANSFER_AMOUNT;189190 console.log('[Unique -> Acala] transaction fees on Acala: %s ACA', acaFees);201 console.log('[Unique -> Acala] transaction fees on Acala: %s ACA', acaFees);191 console.log('[Unique -> Acala] transaction fees on Acala: %s UNQ', unqFees);202 console.log('[Unique -> Acala] income %s UNQ', unqIncomeTransfer);192 expect(acaFees == 0n).to.be.true;203 expect(acaFees == 0n).to.be.true;193 expect(unqFees == 0n).to.be.true;204 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;194 },205 },195 {provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT)},206 acalaOptions(),196 );207 );197 });208 });198 209 221 const id = {232 const id = {222 ForeignAsset: 0,233 ForeignAsset: 0,223 };234 };224 235225 const amount = TRANSFER_AMOUNT;226 const destWeight = 50000000;236 const destWeight = 50000000;227 237 228 const tx = api.tx.xTokens.transfer(id, amount, destination, destWeight);238 const tx = api.tx.xTokens.transfer(id, TRANSFER_AMOUNT, destination, destWeight);229 const events = await submitTransactionAsync(randomAccount, tx);239 const events = await submitTransactionAsync(randomAccount, tx);230 const result = getGenericResult(events);240 const result = getGenericResult(events);231 expect(result.success).to.be.true;241 expect(result.success).to.be.true;236 balanceUniqueForeignTokenFinal = BigInt(free);246 balanceUniqueForeignTokenFinal = BigInt(free);237 }247 }238 248 239 const acaFees = balanceAcalaTokenAfter - balanceAcalaTokenFinal;249 const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal;240 const unqDiffAfterOutcomeTransfer = balanceUniqueForeignTokenAfter - TRANSFER_AMOUNT;250 const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal;241251242 const unqFees = unqDiffAfterOutcomeTransfer - balanceUniqueForeignTokenFinal;243244 console.log('[Acala -> Unique] transaction fees on Acala: %s ACA', acaFees);252 console.log('[Acala -> Unique] transaction fees on Acala: %s ACA', acaFees);245 console.log('[Acala -> Unique] transaction fees on Acala: %s UNQ', unqFees);253 console.log('[Acala -> Unique] outcome %s UNQ', unqOutcomeTransfer);246254247 expect(acaFees > 0).to.be.true;255 expect(acaFees > 0).to.be.true;248 expect(unqFees == 0n).to.be.true;256 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;249 },257 },250 {provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT)},258 acalaOptions(),251 );259 );252260253 // Unique side261 // Unique side254 await usingApi(async (api) => {262 await usingApi(async (api) => {255 // todo do something about instant sealing, where there might not be any new blocks256 await waitNewBlocks(api, 3);263 await waitNewBlocks(api, 3);257 264 258 [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]);265 [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]);259 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenAfter;266 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;260 expect(actuallyDelivered > 0).to.be.true;267 expect(actuallyDelivered > 0).to.be.true;268269 console.log('[Acala -> Unique] actually delivered %s UNQ', actuallyDelivered);261 270 262 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;271 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;263 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', unqFees);272 console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', unqFees);273 expect(unqFees == 0n).to.be.true;274 });275 });276});277278describe('Integration test: Exchanging UNQ with Moonbeam', () => {279280 // Unique constants281 let uniqueAlice: IKeyringPair;282 let uniqueAssetLocation;283284 let randomAccountUnique: IKeyringPair;285 let randomAccountMoonbeam: IKeyringPair;286287 // Moonbeam constants288 let assetId: string;289290 const moonbeamKeyring = new Keyring({type: 'ethereum'});291 const alithPrivateKey = '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133';292 const baltatharPrivateKey = '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b';293 const dorothyPrivateKey = '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68';294295 const alithAccount = moonbeamKeyring.addFromUri(alithPrivateKey, undefined, 'ethereum');296 const baltatharAccount = moonbeamKeyring.addFromUri(baltatharPrivateKey, undefined, 'ethereum');297 const dorothyAccount = moonbeamKeyring.addFromUri(dorothyPrivateKey, undefined, 'ethereum');298299 const councilVotingThreshold = 2;300 const technicalCommitteeThreshold = 2;301 const votingPeriod = 3;302 const delayPeriod = 0;303304 const uniqueAssetMetadata = {305 name: 'xcUnique',306 symbol: 'xcUNQ',307 decimals: 18,308 isFrozen: false,309 minimalBalance: 1,310 };311312 let balanceUniqueTokenInit: bigint;313 let balanceUniqueTokenMiddle: bigint;314 let balanceUniqueTokenFinal: bigint;315 let balanceForeignUnqTokenInit: bigint;316 let balanceForeignUnqTokenMiddle: bigint;317 let balanceForeignUnqTokenFinal: bigint;318 let balanceGlmrTokenInit: bigint;319 let balanceGlmrTokenMiddle: bigint;320 let balanceGlmrTokenFinal: bigint;321322 before(async () => {323 await usingApi(async (api, privateKeyWrapper) => {324 uniqueAlice = privateKeyWrapper('//Alice');325 randomAccountUnique = generateKeyringPair();326 randomAccountMoonbeam = generateKeyringPair('ethereum');327328 balanceForeignUnqTokenInit = 0n;329 });330331 await usingApi(332 async (api) => {333334 // >>> Sponsoring Dorothy >>>335 console.log('Sponsoring Dorothy.......');336 const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n);337 const events0 = await submitTransactionAsync(alithAccount, tx0);338 const result0 = getGenericResult(events0);339 expect(result0.success).to.be.true;340 console.log('Sponsoring Dorothy.......DONE');341 // <<< Sponsoring Dorothy <<<342343 const sourceLocation: MultiLocation = api.createType(344 'MultiLocation',345 {346 parents: 1,347 interior: {X1: {Parachain: UNIQUE_CHAIN}},348 },349 );350351 uniqueAssetLocation = {XCM: sourceLocation};352 const existentialDeposit = 1;353 const isSufficient = true;354 const unitsPerSecond = '1';355 const numAssetsWeightHint = 0;356357 const registerTx = api.tx.assetManager.registerForeignAsset(358 uniqueAssetLocation,359 uniqueAssetMetadata,360 existentialDeposit,361 isSufficient,362 );363 console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || '');364365 const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond(366 uniqueAssetLocation,367 unitsPerSecond,368 numAssetsWeightHint,369 );370 console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || '');371372 const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]);373 console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || '');374375 // >>> Note motion preimage >>>376 console.log('Note motion preimage.......');377 const encodedProposal = batchCall?.method.toHex() || '';378 const proposalHash = blake2AsHex(encodedProposal);379 console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal);380 console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash);381 console.log('Encoded length %d', encodedProposal.length);382383 const tx1 = api.tx.democracy.notePreimage(encodedProposal);384 const events1 = await submitTransactionAsync(baltatharAccount, tx1);385 const result1 = getGenericResult(events1);386 expect(result1.success).to.be.true;387 console.log('Note motion preimage.......DONE');388 // <<< Note motion preimage <<<389390 // >>> Propose external motion through council >>>391 console.log('Propose external motion through council.......');392 const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash);393 const tx2 = api.tx.councilCollective.propose(394 councilVotingThreshold,395 externalMotion,396 externalMotion.encodedLength,397 );398 const events2 = await submitTransactionAsync(baltatharAccount, tx2);399 const result2 = getGenericResult(events2);400 expect(result2.success).to.be.true;401402 const encodedMotion = externalMotion?.method.toHex() || '';403 const motionHash = blake2AsHex(encodedMotion);404 console.log('Motion hash is %s', motionHash);405406 const tx3 = api.tx.councilCollective.vote(motionHash, 0, true);407 {408 const events3 = await submitTransactionAsync(dorothyAccount, tx3);409 const result3 = getGenericResult(events3);410 expect(result3.success).to.be.true;411 }412 {413 const events3 = await submitTransactionAsync(baltatharAccount, tx3);414 const result3 = getGenericResult(events3);415 expect(result3.success).to.be.true;416 }417418 const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength);419 const events4 = await submitTransactionAsync(dorothyAccount, tx4);420 const result4 = getGenericResult(events4);421 expect(result4.success).to.be.true;422 console.log('Propose external motion through council.......DONE');423 // <<< Propose external motion through council <<<424425 // >>> Fast track proposal through technical committee >>>426 console.log('Fast track proposal through technical committee.......');427 const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod);428 const tx5 = api.tx.techCommitteeCollective.propose(429 technicalCommitteeThreshold,430 fastTrack,431 fastTrack.encodedLength,432 );433 const events5 = await submitTransactionAsync(alithAccount, tx5);434 const result5 = getGenericResult(events5);435 expect(result5.success).to.be.true;436437 const encodedFastTrack = fastTrack?.method.toHex() || '';438 const fastTrackHash = blake2AsHex(encodedFastTrack);439 console.log('FastTrack hash is %s', fastTrackHash);440441 const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1;442 const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true);443 {444 const events6 = await submitTransactionAsync(baltatharAccount, tx6);445 const result6 = getGenericResult(events6);446 expect(result6.success).to.be.true;447 }448 {449 const events6 = await submitTransactionAsync(alithAccount, tx6);450 const result6 = getGenericResult(events6);451 expect(result6.success).to.be.true;452 }453454 const tx7 = api.tx.techCommitteeCollective455 .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength);456 const events7 = await submitTransactionAsync(baltatharAccount, tx7);457 const result7 = getGenericResult(events7);458 expect(result7.success).to.be.true;459 console.log('Fast track proposal through technical committee.......DONE');460 // <<< Fast track proposal through technical committee <<<461462 // >>> Referendum voting >>>463 console.log('Referendum voting.......');464 const tx8 = api.tx.democracy.vote(465 0,466 {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}},467 );468 const events8 = await submitTransactionAsync(dorothyAccount, tx8);469 const result8 = getGenericResult(events8);470 expect(result8.success).to.be.true;471 console.log('Referendum voting.......DONE');472 // <<< Referendum voting <<<473474 // >>> Acquire Unique AssetId Info on Moonbeam >>>475 console.log('Acquire Unique AssetId Info on Moonbeam.......');476477 // Wait for the democracy execute478 await waitNewBlocks(api, 5);479480 assetId = (await api.query.assetManager.assetTypeId({481 XCM: sourceLocation,482 })).toString();483484 console.log('UNQ asset ID is %s', assetId);485 console.log('Acquire Unique AssetId Info on Moonbeam.......DONE');486 // >>> Acquire Unique AssetId Info on Moonbeam >>>487488 // >>> Sponsoring random Account >>>489 console.log('Sponsoring random Account.......');490 const tx10 = api.tx.balances.transfer(randomAccountMoonbeam.address, 11_000_000_000_000_000_000n);491 const events10 = await submitTransactionAsync(baltatharAccount, tx10);492 const result10 = getGenericResult(events10);493 expect(result10.success).to.be.true;494 console.log('Sponsoring random Account.......DONE');495 // <<< Sponsoring random Account <<<496497 [balanceGlmrTokenInit] = await getBalance(api, [randomAccountMoonbeam.address]);498 },499 moonbeamOptions(),500 );501502 await usingApi(async (api) => {503 const tx0 = api.tx.balances.transfer(randomAccountUnique.address, 10n * TRANSFER_AMOUNT);504 const events0 = await submitTransactionAsync(uniqueAlice, tx0);505 const result0 = getGenericResult(events0);506 expect(result0.success).to.be.true;507508 [balanceUniqueTokenInit] = await getBalance(api, [randomAccountUnique.address]);509 });510 });511512 it('Should connect and send UNQ to Moonbeam', async () => {513 await usingApi(async (api) => {514 const currencyId = {515 NativeAssetId: 'Here',516 };517 const dest = {518 V1: {519 parents: 1,520 interior: {521 X2: [522 {Parachain: MOONBEAM_CHAIN},523 {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}},524 ],525 },526 },527 };528 const amount = TRANSFER_AMOUNT;529 const destWeight = 850000000;530531 const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeight);532 const events = await submitTransactionAsync(randomAccountUnique, tx);533 const result = getGenericResult(events);534 expect(result.success).to.be.true;535536 [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccountUnique.address]);537 expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true;538539 const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle + TRANSFER_AMOUNT;540 console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', transactionFees);541 expect(transactionFees > 0).to.be.true;542 });543544 await usingApi(545 async (api) => {546 await waitNewBlocks(api, 3);547548 [balanceGlmrTokenMiddle] = await getBalance(api, [randomAccountMoonbeam.address]);549550 const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle;551 console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', glmrFees);552 expect(glmrFees == 0n).to.be.true;553554 const unqRandomAccountAsset = (555 await api.query.assets.account(assetId, randomAccountMoonbeam.address)556 ).toJSON()! as any;557558 balanceForeignUnqTokenMiddle = BigInt(unqRandomAccountAsset['balance']);559 const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit;560 console.log('[Unique -> Moonbeam] income %s UNQ', unqIncomeTransfer);561 expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true;562 },563 moonbeamOptions(),564 );565 });566567 it('Should connect to Moonbeam and send UNQ back', async () => {568 await usingApi(569 async (api) => {570 const asset = {571 V1: {572 id: {573 Concrete: {574 parents: 1,575 interior: {576 X1: {Parachain: UNIQUE_CHAIN},577 },578 },579 },580 fun: {581 Fungible: TRANSFER_AMOUNT,582 },583 },584 };585 const destination = {586 V1: {587 parents: 1,588 interior: {589 X2: [590 {Parachain: UNIQUE_CHAIN},591 {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}},592 ],593 },594 },595 };596 const destWeight = 50000000;597598 const tx = api.tx.xTokens.transferMultiasset(asset, destination, destWeight);599 const events = await submitTransactionAsync(randomAccountMoonbeam, tx);600 const result = getGenericResult(events);601 expect(result.success).to.be.true;602603 [balanceGlmrTokenFinal] = await getBalance(api, [randomAccountMoonbeam.address]);604605 const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal;606 console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', glmrFees);607 expect(glmrFees > 0).to.be.true;608609 const unqRandomAccountAsset = (610 await api.query.assets.account(assetId, randomAccountMoonbeam.address)611 ).toJSON()! as any;612613 expect(unqRandomAccountAsset).to.be.null;614615 balanceForeignUnqTokenFinal = 0n;616617 const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal;618 console.log('[Unique -> Moonbeam] outcome %s UNQ', unqOutcomeTransfer);619 expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true;620 },621 moonbeamOptions(),622 );623624 await usingApi(async (api) => {625 await waitNewBlocks(api, 3);626627 [balanceUniqueTokenFinal] = await getBalance(api, [randomAccountUnique.address]);628 const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle;629 expect(actuallyDelivered > 0).to.be.true;630631 console.log('[Moonbeam -> Unique] actually delivered %s UNQ', actuallyDelivered);632633 const unqFees = TRANSFER_AMOUNT - actuallyDelivered;634 console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', unqFees);264 expect(unqFees == 0n).to.be.true;635 expect(unqFees == 0n).to.be.true;265 });636 });266 });637 });