From 183fa35b79fd357d9e88d349e84c1d10dbc61d28 Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Tue, 30 Aug 2022 14:42:49 +0000 Subject: [PATCH] test(xcm): add XCM Unique --- --- a/tests/package.json +++ b/tests/package.json @@ -74,6 +74,7 @@ "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts", "testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.test.ts", "testSchedulingEVM": "mocha --timeout 9999999 -r ts-node/register ./**/eth/scheduling.test.ts", + "testXcmUnique": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmUnique.test.ts", "testXcmTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransfer.test.ts", "testXcmTransferAcala": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferAcala.test.ts acalaId=2000 uniqueId=5000", "testXcmTransferStatemine": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferStatemine.test.ts statemineId=1000 uniqueId=5000", --- /dev/null +++ b/tests/src/xcm/xcmUnique.test.ts @@ -0,0 +1,267 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import {WsProvider} from '@polkadot/api'; +import {ApiOptions} from '@polkadot/api/types'; +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult, generateKeyringPair} from '../util/helpers'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import getBalance from '../substrate/get-balance'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const UNIQUE_CHAIN = 2037; +const ACALA_CHAIN = 2000; + +const ACALA_PORT = '9946'; + +const TRANSFER_AMOUNT = 2000000000000000000000000n; + +describe('Integration test: Exchanging UNQ with Acala', () => { + let alice: IKeyringPair; + let randomAccount: IKeyringPair; + + let balanceUniqueTokenBefore: bigint; + let balanceUniqueTokenAfter: bigint; + let balanceUniqueTokenFinal: bigint; + let balanceAcalaTokenBefore: bigint; + let balanceAcalaTokenAfter: bigint; + let balanceAcalaTokenFinal: bigint; + let balanceUniqueForeignTokenAfter: bigint; + let balanceUniqueForeignTokenBefore: bigint; + let balanceUniqueForeignTokenFinal: bigint; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + randomAccount = generateKeyringPair(); + }); + + const acalaApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT), + }; + + // Acala side + await usingApi( + async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: UNIQUE_CHAIN, + }, + ], + }, + }; + + const metadata = { + name: 'UNQ', + symbol: 'UNQ', + decimals: 18, + minimalBalance: 1, + }; + + const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata); + const sudoTx = api.tx.sudo.sudo(tx as any); + const events = await submitTransactionAsync(alice, sudoTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n); + const events1 = await submitTransactionAsync(alice, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + + [balanceAcalaTokenBefore] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenBefore = BigInt(free); + } + }, + acalaApiOptions, + ); + + // Unique side + await usingApi(async (api) => { + const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT); + const events0 = await submitTransactionAsync(alice, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + + [balanceUniqueTokenBefore] = await getBalance(api, [randomAccount.address]); + }); + }); + + it('Should connect and send UNQ to Acala', async () => { + + // Unique side + await usingApi(async (api) => { + + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: ACALA_CHAIN, + }, + ], + }, + }; + + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5000000000, + }; + + const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceUniqueTokenAfter] = await getBalance(api, [randomAccount.address]); + + const unqFees = balanceUniqueTokenBefore - balanceUniqueTokenAfter; + console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', unqFees); + expect(unqFees > 0n).to.be.true; + }); + + // Acala side + await usingApi( + async (api) => { + // todo do something about instant sealing, where there might not be any new blocks + await waitNewBlocks(api, 3); + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenAfter = BigInt(free); + + [balanceAcalaTokenAfter] = await getBalance(api, [randomAccount.address]); + + const acaFees = balanceAcalaTokenBefore - balanceAcalaTokenAfter; + const unqDiffAfterIncomeTransfer = balanceUniqueForeignTokenAfter - balanceUniqueForeignTokenBefore; + + const unqFees = unqDiffAfterIncomeTransfer - TRANSFER_AMOUNT; + + console.log('[Unique -> Acala] transaction fees on Acala: %s ACA', acaFees); + console.log('[Unique -> Acala] transaction fees on Acala: %s UNQ', unqFees); + expect(acaFees == 0n).to.be.true; + expect(unqFees == 0n).to.be.true; + }, + {provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT)}, + ); + }); + + it('Should connect to Acala and send UNQ back', async () => { + + // Acala side + await usingApi( + async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + ], + }, + }, + }; + + const id = { + ForeignAsset: 0, + }; + + const amount = TRANSFER_AMOUNT; + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id, amount, destination, destWeight); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenFinal = BigInt(free); + } + + const acaFees = balanceAcalaTokenAfter - balanceAcalaTokenFinal; + const unqDiffAfterOutcomeTransfer = balanceUniqueForeignTokenAfter - TRANSFER_AMOUNT; + + const unqFees = unqDiffAfterOutcomeTransfer - balanceUniqueForeignTokenFinal; + + console.log('[Acala -> Unique] transaction fees on Acala: %s ACA', acaFees); + console.log('[Acala -> Unique] transaction fees on Acala: %s UNQ', unqFees); + + expect(acaFees > 0).to.be.true; + expect(unqFees == 0n).to.be.true; + }, + {provider: new WsProvider('ws://127.0.0.1:' + ACALA_PORT)}, + ); + + // Unique side + await usingApi(async (api) => { + // todo do something about instant sealing, where there might not be any new blocks + await waitNewBlocks(api, 3); + + [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]); + const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenAfter; + expect(actuallyDelivered > 0).to.be.true; + + const unqFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', unqFees); + expect(unqFees == 0n).to.be.true; + }); + }); + }); -- gitstuff