--- a/tests/src/xcm/xcmOpal.test.ts +++ b/tests/src/xcm/xcmOpal.test.ts @@ -14,33 +14,27 @@ // 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, {executeTransaction} from './../substrate/substrate-api'; -import {bigIntToDecimals, describe_xcm, getGenericResult, paraSiblingSovereignAccount, normalizeAccountId} from './../deprecated-helpers/helpers'; -import waitNewBlocks from './../substrate/wait-new-blocks'; +import {executeTransaction} from './../substrate/substrate-api'; +import {bigIntToDecimals, getGenericResult, paraSiblingSovereignAccount} from './../deprecated-helpers/helpers'; import getBalance from './../substrate/get-balance'; - - -chai.use(chaiAsPromised); -const expect = chai.expect; +import {itSub, expect, describeXcm, usingPlaygrounds} from '../util/playgrounds'; const STATEMINE_CHAIN = 1000; const UNIQUE_CHAIN = 2095; const RELAY_PORT = '9844'; -const UNIQUE_PORT = '9944'; const STATEMINE_PORT = '9948'; + +const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT; +const statemineUrl = 'ws://127.0.0.1:' + STATEMINE_PORT; + const STATEMINE_PALLET_INSTANCE = 50; const ASSET_ID = 100; const ASSET_METADATA_DECIMALS = 18; const ASSET_METADATA_NAME = 'USDT'; const ASSET_METADATA_DESCRIPTION = 'USDT'; -const ASSET_METADATA_MINIMAL_BALANCE = 1; +const ASSET_METADATA_MINIMAL_BALANCE = 1n; const WESTMINT_DECIMALS = 12; @@ -49,7 +43,7 @@ // 10,000.00 (ten thousands) USDT const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; -describe_xcm('[XCM] Integration test: Exchanging USDT with Westmint', () => { +describeXcm('[XCM] Integration test: Exchanging USDT with Westmint', () => { let alice: IKeyringPair; let bob: IKeyringPair; @@ -69,24 +63,13 @@ before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); // funds donor + await usingPlaygrounds(async (_helper, privateKey) => { + alice = privateKey('//Alice'); + bob = privateKey('//Bob'); // funds donor }); - - const statemineApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), - }; - const uniqueApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), - }; - - const relayApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + RELAY_PORT), - }; - - await usingApi(async (api) => { + await usingPlaygrounds.atUrl(statemineUrl, async (helper) => { + const api = helper.getApi(); // 350.00 (three hundred fifty) DOT const fundingAmount = 3_500_000_000_000; @@ -115,11 +98,10 @@ const result4 = getGenericResult(events4); expect(result4.success).to.be.true; - }, statemineApiOptions); + }); - await usingApi(async (api) => { - + await usingPlaygrounds(async (helper) => { const location = { V1: { parents: 1, @@ -144,20 +126,23 @@ decimals: ASSET_METADATA_DECIMALS, minimalBalance: ASSET_METADATA_MINIMAL_BALANCE, }; - //registerForeignAsset(owner, location, metadata) - const tx = api.tx.foreignAssets.registerForeignAsset(alice.addressRaw, location, metadata); - const sudoTx = api.tx.sudo.sudo(tx as any); - const events = await executeTransaction(api, alice, sudoTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + await helper.getSudo().foreignAssets.register(alice, alice.address, location, metadata); + // const tx = api.tx.foreignAssets.registerForeignAsset(alice.addressRaw, location, metadata); + // const sudoTx = api.tx.sudo.sudo(tx as any); + // const events = await executeTransaction(api, alice, sudoTx); + // const result = getGenericResult(events); + // expect(result.success).to.be.true; - [balanceOpalBefore] = await getBalance(api, [alice.address]); + // [balanceOpalBefore] = await getBalance(api, [alice.address]); + balanceOpalBefore = await helper.balance.getSubstrate(alice.address); - }, uniqueApiOptions); + }); // Providing the relay currency to the unique sender account - await usingApi(async (api) => { + await usingPlaygrounds.atUrl(relayUrl, async (helper) => { + const api = helper.getApi(); + const destination = { V1: { parents: 0, @@ -205,22 +190,14 @@ const events = await executeTransaction(api, alice, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, relayApiOptions); + }); }); - it('Should connect and send USDT from Westmint to Opal', async () => { - - const statemineApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), - }; - - const uniqueApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), - }; + itSub('Should connect and send USDT from Westmint to Opal', async ({helper}) => { + await usingPlaygrounds.atUrl(statemineUrl, async (helper) => { + const api = helper.getApi(); - await usingApi(async (api) => { - const dest = { V1: { parents: 1, @@ -288,125 +265,109 @@ ); expect(balanceStmnBefore > balanceStmnAfter).to.be.true; - }, statemineApiOptions); + }); // ensure that asset has been delivered - await usingApi(async (api) => { - await waitNewBlocks(api, 3); - // expext collection id will be with id 1 - const free = (await api.query.fungible.balance(1, normalizeAccountId(alice.address))).toBigInt(); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceOpalAfter] = await getBalance(api, [alice.address]); + // expext collection id will be with id 1 + // const free = (await api.query.fungible.balance(1, normalizeAccountId(alice.address))).toBigInt(); + const free = await helper.ft.getBalance(1, {Substrate: alice.address}); - // commission has not paid in USDT token - expect(free == TRANSFER_AMOUNT).to.be.true; - console.log( - 'Opal to Westmint transaction fees on Opal: %s USDT', - bigIntToDecimals(TRANSFER_AMOUNT - free), - ); - // ... and parachain native token - expect(balanceOpalAfter == balanceOpalBefore).to.be.true; - console.log( - 'Opal to Westmint transaction fees on Opal: %s WND', - bigIntToDecimals(balanceOpalAfter - balanceOpalBefore, WESTMINT_DECIMALS), - ); + // [balanceOpalAfter] = await getBalance(api, [alice.address]); + balanceOpalAfter = await helper.balance.getSubstrate(alice.address); - }, uniqueApiOptions); - + // commission has not paid in USDT token + expect(free == TRANSFER_AMOUNT).to.be.true; + console.log( + 'Opal to Westmint transaction fees on Opal: %s USDT', + bigIntToDecimals(TRANSFER_AMOUNT - free), + ); + // ... and parachain native token + expect(balanceOpalAfter == balanceOpalBefore).to.be.true; + console.log( + 'Opal to Westmint transaction fees on Opal: %s WND', + bigIntToDecimals(balanceOpalAfter - balanceOpalBefore, WESTMINT_DECIMALS), + ); }); - it('Should connect and send USDT from Unique to Statemine back', async () => { + itSub('Should connect and send USDT from Unique to Statemine back', async ({helper}) => { + const api = helper.getApi(); - const uniqueApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), - }; - - const statemineApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), + const destination = { + V1: { + parents: 1, + interior: {X2: [ + { + Parachain: STATEMINE_CHAIN, + }, + { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }, + ]}, + }, }; - await usingApi(async (api) => { - const destination = { - V1: { - parents: 1, - interior: {X2: [ - { - Parachain: STATEMINE_CHAIN, - }, - { - AccountId32: { - network: 'Any', - id: alice.addressRaw, - }, - }, - ]}, + const currencies: [any, bigint][] = [ + [ + { + ForeignAssetId: 0, + }, + //10_000_000_000_000_000n, + TRANSFER_AMOUNT, + ], + [ + { + NativeAssetId: 'Parent', }, - }; + 400_000_000_000_000n, + ], + ]; - const currencies: [any, bigint][] = [ - [ - { - ForeignAssetId: 0, - }, - //10_000_000_000_000_000n, - TRANSFER_AMOUNT, - ], - [ - { - NativeAssetId: 'Parent', - }, - 400_000_000_000_000n, - ], - ]; + const feeItem = 1; + const destWeight = 500000000000; - const feeItem = 1; - const destWeight = 500000000000; + const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); + const events = await executeTransaction(api, alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + // the commission has been paid in parachain native token + [balanceOpalFinal] = await getBalance(api, [alice.address]); + expect(balanceOpalAfter > balanceOpalFinal).to.be.true; - const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); - const events = await executeTransaction(api, alice, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - // the commission has been paid in parachain native token - [balanceOpalFinal] = await getBalance(api, [alice.address]); - expect(balanceOpalAfter > balanceOpalFinal).to.be.true; - }, uniqueApiOptions); + await usingPlaygrounds.atUrl(statemineUrl, async (helper) => { + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + const api = helper.getApi(); // The USDT token never paid fees. Its amount not changed from begin value. // Also check that xcm transfer has been succeeded const free = ((await api.query.assets.account(100, alice.address)).toHuman()) as any; expect(BigInt(free.balance.replace(/,/g, '')) == ASSET_AMOUNT).to.be.true; - }, statemineApiOptions); + }); }); - - it('Should connect and send Relay token to Unique', async () => { - const uniqueApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), - }; - - const uniqueApiOptions2: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), - }; - - const relayApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + RELAY_PORT), - }; - + itSub('Should connect and send Relay token to Unique', async ({helper}) => { const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n; - await usingApi(async (api) => { - [balanceBobBefore] = await getBalance(api, [bob.address]); - balanceBobRelayTokenBefore = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + // [balanceBobBefore] = await getBalance(api, [bob.address]); + // balanceBobRelayTokenBefore = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + balanceBobBefore = await helper.balance.getSubstrate(bob.address); - }, uniqueApiOptions); + // TODO + balanceBobRelayTokenBefore = BigInt(((await helper.getApi().query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); // Providing the relay currency to the unique sender account - await usingApi(async (api) => { + await usingPlaygrounds.atUrl(relayUrl, async (helper) => { + const api = helper.getApi(); + const destination = { V1: { parents: 0, @@ -454,73 +415,72 @@ const events = await executeTransaction(api, bob, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, relayApiOptions); + }); - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceBobAfter] = await getBalance(api, [bob.address]); - balanceBobRelayTokenAfter = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); - const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; - console.log( - 'Relay (Westend) to Opal transaction fees: %s OPL', - bigIntToDecimals(balanceBobAfter - balanceBobBefore), - ); - console.log( - 'Relay (Westend) to Opal transaction fees: %s WND', - bigIntToDecimals(wndFee, WESTMINT_DECIMALS), - ); - expect(balanceBobBefore == balanceBobAfter).to.be.true; - expect(balanceBobRelayTokenBefore < balanceBobRelayTokenAfter).to.be.true; - }, uniqueApiOptions2); + // [balanceBobAfter] = await getBalance(api, [bob.address]); + // balanceBobRelayTokenAfter = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + balanceBobAfter = await helper.balance.getSubstrate(bob.address); + + // TODO + balanceBobRelayTokenAfter = BigInt(((await helper.getApi().query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; + console.log( + 'Relay (Westend) to Opal transaction fees: %s OPL', + bigIntToDecimals(balanceBobAfter - balanceBobBefore), + ); + console.log( + 'Relay (Westend) to Opal transaction fees: %s WND', + bigIntToDecimals(wndFee, WESTMINT_DECIMALS), + ); + expect(balanceBobBefore == balanceBobAfter).to.be.true; + expect(balanceBobRelayTokenBefore < balanceBobRelayTokenAfter).to.be.true; }); - it('Should connect and send Relay token back', async () => { - const uniqueApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + itSub('Should connect and send Relay token back', async ({helper}) => { + const destination = { + V1: { + parents: 1, + interior: {X2: [ + { + Parachain: STATEMINE_CHAIN, + }, + { + AccountId32: { + network: 'Any', + id: bob.addressRaw, + }, + }, + ]}, + }, }; - await usingApi(async (api) => { - const destination = { - V1: { - parents: 1, - interior: {X2: [ - { - Parachain: STATEMINE_CHAIN, - }, - { - AccountId32: { - network: 'Any', - id: bob.addressRaw, - }, - }, - ]}, + const currencies: any = [ + [ + { + NativeAssetId: 'Parent', }, - }; - - const currencies: any = [ - [ - { - NativeAssetId: 'Parent', - }, - 50_000_000_000_000_000n, - ], - ]; - - const feeItem = 0; - const destWeight = 500000000000; + 50_000_000_000_000_000n, + ], + ]; - const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); - const events = await executeTransaction(api, bob, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + const feeItem = 0; + const destWeight = 500000000000; - [balanceBobFinal] = await getBalance(api, [bob.address]); - console.log('Relay (Westend) to Opal transaction fees: %s OPL', balanceBobAfter - balanceBobFinal); + // TODO + const api = helper.getApi(); + const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); + const events = await executeTransaction(api, bob, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - }, uniqueApiOptions); + // [balanceBobFinal] = await getBalance(api, [bob.address]); + balanceBobFinal = await helper.balance.getSubstrate(bob.address); + console.log('Relay (Westend) to Opal transaction fees: %s OPL', balanceBobAfter - balanceBobFinal); }); }); --- a/tests/src/xcm/xcmQuartz.test.ts +++ b/tests/src/xcm/xcmQuartz.test.ts @@ -14,23 +14,16 @@ // 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, Keyring} from '@polkadot/api'; -import {ApiOptions} from '@polkadot/api/types'; +import {Keyring} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; -import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; -import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../deprecated-helpers/helpers'; +import {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult, generateKeyringPair, waitEvent, bigIntToDecimals} from '../deprecated-helpers/helpers'; import {MultiLocation} from '@polkadot/types/interfaces'; import {blake2AsHex} from '@polkadot/util-crypto'; -import waitNewBlocks from '../substrate/wait-new-blocks'; import getBalance from '../substrate/get-balance'; import {XcmV2TraitsOutcome, XcmV2TraitsError} from '../interfaces'; +import {itSub, expect, describeXcm, usingPlaygrounds} from '../util/playgrounds'; -chai.use(chaiAsPromised); -const expect = chai.expect; - const QUARTZ_CHAIN = 2095; const KARURA_CHAIN = 2000; const MOONRIVER_CHAIN = 2023; @@ -39,29 +32,15 @@ const KARURA_PORT = 9946; const MOONRIVER_PORT = 9947; +const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT; +const karuraUrl = 'ws://127.0.0.1:' + KARURA_PORT; +const moonriverUrl = 'ws://127.0.0.1:' + MOONRIVER_PORT; + const KARURA_DECIMALS = 12; const TRANSFER_AMOUNT = 2000000000000000000000000n; -function parachainApiOptions(port: number): ApiOptions { - return { - provider: new WsProvider('ws://127.0.0.1:' + port.toString()), - }; -} - -function karuraOptions(): ApiOptions { - return parachainApiOptions(KARURA_PORT); -} - -function moonriverOptions(): ApiOptions { - return parachainApiOptions(MOONRIVER_PORT); -} - -function relayOptions(): ApiOptions { - return parachainApiOptions(RELAY_PORT); -} - -describe_xcm('[XCM] Integration test: Exchanging tokens with Karura', () => { +describeXcm('[XCM] Integration test: Exchanging tokens with Karura', () => { let alice: IKeyringPair; let randomAccount: IKeyringPair; @@ -76,233 +55,234 @@ let balanceQuartzForeignTokenFinal: bigint; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { + await usingPlaygrounds(async (helper, privateKey) => { const keyringSr25519 = new Keyring({type: 'sr25519'}); - alice = privateKeyWrapper('//Alice'); + alice = privateKey('//Alice'); randomAccount = generateKeyringPair(keyringSr25519); }); // Karura side - await usingApi( - async (api) => { - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: QUARTZ_CHAIN, - }, - ], - }, - }; + await usingPlaygrounds.atUrl(karuraUrl, async (helper) => { + const api = helper.getApi(); + + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: QUARTZ_CHAIN, + }, + ], + }, + }; - const metadata = { - name: 'QTZ', - symbol: 'QTZ', - decimals: 18, - minimalBalance: 1, - }; + const metadata = { + name: 'QTZ', + symbol: 'QTZ', + 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 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; + 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; - [balanceKaruraTokenInit] = await getBalance(api, [randomAccount.address]); - { - const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; - balanceQuartzForeignTokenInit = BigInt(free); - } - }, - karuraOptions(), - ); + [balanceKaruraTokenInit] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceQuartzForeignTokenInit = BigInt(free); + } + }); // Quartz 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; + await usingPlaygrounds(async (helper) => { + // 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; + await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT); - [balanceQuartzTokenInit] = await getBalance(api, [randomAccount.address]); + // [balanceQuartzTokenInit] = await getBalance(api, [randomAccount.address]); + balanceQuartzTokenInit = await helper.balance.getSubstrate(randomAccount.address); }); }); - it('Should connect and send QTZ to Karura', async () => { + itSub('Should connect and send QTZ to Karura', async ({helper}) => { // Quartz side - await usingApi(async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: KARURA_CHAIN, + }, + ], + }, + }; - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: KARURA_CHAIN, - }, - ], + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, }, - }; + }, + }; - const beneficiary = { - V0: { - X1: { - AccountId32: { - network: 'Any', - id: randomAccount.addressRaw, + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', }, }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, }, - }; + ], + }; - const assets = { - V1: [ - { - id: { - Concrete: { - parents: 0, - interior: 'Here', - }, - }, - fun: { - Fungible: TRANSFER_AMOUNT, - }, - }, - ], - }; + const feeAssetItem = 0; - const feeAssetItem = 0; - - const weightLimit = { - Limited: 5000000000, - }; + 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; + // TODO + const tx = helper.getApi().tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccount.address]); + // [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccount.address]); + balanceQuartzTokenMiddle = await helper.balance.getSubstrate(randomAccount.address); - const qtzFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; - console.log('[Quartz -> Karura] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); - expect(qtzFees > 0n).to.be.true; - }); + const qtzFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; + console.log('[Quartz -> Karura] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees > 0n).to.be.true; // Karura side - await usingApi( - async (api) => { - await waitNewBlocks(api, 3); - const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; - balanceQuartzForeignTokenMiddle = BigInt(free); + await usingPlaygrounds.atUrl(karuraUrl, async (helper) => { + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); + + // TODO + const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceQuartzForeignTokenMiddle = BigInt(free); - [balanceKaruraTokenMiddle] = await getBalance(api, [randomAccount.address]); + // [balanceKaruraTokenMiddle] = await getBalance(api, [randomAccount.address]); + balanceKaruraTokenMiddle = await helper.balance.getSubstrate(randomAccount.address); - const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle; - const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit; + const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle; + const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit; - console.log( - '[Quartz -> Karura] transaction fees on Karura: %s KAR', - bigIntToDecimals(karFees, KARURA_DECIMALS), - ); - console.log('[Quartz -> Karura] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); - expect(karFees == 0n).to.be.true; - expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - karuraOptions(), - ); + console.log( + '[Quartz -> Karura] transaction fees on Karura: %s KAR', + bigIntToDecimals(karFees, KARURA_DECIMALS), + ); + console.log('[Quartz -> Karura] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); + expect(karFees == 0n).to.be.true; + expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); }); - it('Should connect to Karura and send QTZ back', async () => { + itSub('Should connect to Karura and send QTZ back', async ({helper}) => { // Karura side - await usingApi( - async (api) => { - const destination = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: QUARTZ_CHAIN}, - { - AccountId32: { - network: 'Any', - id: randomAccount.addressRaw, - }, + await usingPlaygrounds.atUrl(karuraUrl, async (helper) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: QUARTZ_CHAIN}, + { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, }, - ], - }, + }, + ], }, - }; + }, + }; - const id = { - ForeignAsset: 0, - }; + const id = { + ForeignAsset: 0, + }; - const destWeight = 50000000; + const destWeight = 50000000; - const tx = api.tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight); - const events = await submitTransactionAsync(randomAccount, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceKaruraTokenFinal] = await getBalance(api, [randomAccount.address]); - { - const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any; - balanceQuartzForeignTokenFinal = BigInt(free); - } + // [balanceKaruraTokenFinal] = await getBalance(api, [randomAccount.address]); + balanceKaruraTokenFinal = await helper.balance.getSubstrate(randomAccount.address); + { + // TODO + const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any; + balanceQuartzForeignTokenFinal = BigInt(free); + } - const karFees = balanceKaruraTokenMiddle - balanceKaruraTokenFinal; - const qtzOutcomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenFinal; + const karFees = balanceKaruraTokenMiddle - balanceKaruraTokenFinal; + const qtzOutcomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenFinal; - console.log( - '[Karura -> Quartz] transaction fees on Karura: %s KAR', - bigIntToDecimals(karFees, KARURA_DECIMALS), - ); - console.log('[Karura -> Quartz] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); + console.log( + '[Karura -> Quartz] transaction fees on Karura: %s KAR', + bigIntToDecimals(karFees, KARURA_DECIMALS), + ); + console.log('[Karura -> Quartz] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); - expect(karFees > 0).to.be.true; - expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - karuraOptions(), - ); + expect(karFees > 0).to.be.true; + expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); // Quartz side - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceQuartzTokenFinal] = await getBalance(api, [randomAccount.address]); - const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; - expect(actuallyDelivered > 0).to.be.true; + // [balanceQuartzTokenFinal] = await getBalance(api, [randomAccount.address]); + balanceQuartzTokenFinal = await helper.balance.getSubstrate(randomAccount.address); + const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; - console.log('[Karura -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); + console.log('[Karura -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); - const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; - console.log('[Karura -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); - expect(qtzFees == 0n).to.be.true; - }); + const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Karura -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees == 0n).to.be.true; }); }); // These tests are relevant only when the foreign asset pallet is disabled -describe_xcm('[XCM] Integration test: Quartz rejects non-native tokens', () => { +describeXcm('[XCM] Integration test: Quartz rejects non-native tokens', () => { let alice: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); + await usingPlaygrounds(async (_helper, privateKey) => { + alice = privateKey('//Alice'); }); }); - it('Quartz rejects tokens from the Relay', async () => { - await usingApi(async (api) => { + itSub('Quartz rejects tokens from the Relay', async ({helper}) => { + await usingPlaygrounds.atUrl(relayUrl, async (helper) => { const destination = { V1: { parents: 0, @@ -346,44 +326,45 @@ Limited: 5_000_000_000, }; - const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + // TODO + const tx = helper.getApi().tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, relayOptions()); + }); - await usingApi(async api => { - const maxWaitBlocks = 3; - const dmpQueueExecutedDownward = await waitEvent( - api, - maxWaitBlocks, - 'dmpQueue', - 'ExecutedDownward', - ); + const maxWaitBlocks = 3; - expect( - dmpQueueExecutedDownward != null, - '[Relay] dmpQueue.ExecutedDownward event is expected', - ).to.be.true; + // TODO + const dmpQueueExecutedDownward = await waitEvent( + helper.getApi(), + maxWaitBlocks, + 'dmpQueue', + 'ExecutedDownward', + ); - const event = dmpQueueExecutedDownward!.event; - const outcome = event.data[1] as XcmV2TraitsOutcome; + expect( + dmpQueueExecutedDownward != null, + '[Relay] dmpQueue.ExecutedDownward event is expected', + ).to.be.true; - expect( - outcome.isIncomplete, - '[Relay] The outcome of the XCM should be `Incomplete`', - ).to.be.true; + const event = dmpQueueExecutedDownward!.event; + const outcome = event.data[1] as XcmV2TraitsOutcome; + + expect( + outcome.isIncomplete, + '[Relay] The outcome of the XCM should be `Incomplete`', + ).to.be.true; - const incomplete = outcome.asIncomplete; - expect( - incomplete[1].toString() == 'AssetNotFound', - '[Relay] The XCM error should be `AssetNotFound`', - ).to.be.true; - }); + const incomplete = outcome.asIncomplete; + expect( + incomplete[1].toString() == 'AssetNotFound', + '[Relay] The XCM error should be `AssetNotFound`', + ).to.be.true; }); - it('Quartz rejects KAR tokens from Karura', async () => { - await usingApi(async (api) => { + itSub('Quartz rejects KAR tokens from Karura', async ({helper}) => { + await usingPlaygrounds.atUrl(karuraUrl, async (helper) => { const destination = { V1: { parents: 1, @@ -407,33 +388,34 @@ const destWeight = 50000000; - const tx = api.tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); + // TODO + const tx = helper.getApi().tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, karuraOptions()); + }); - await usingApi(async api => { - const maxWaitBlocks = 3; - const xcmpQueueFailEvent = await waitEvent(api, maxWaitBlocks, 'xcmpQueue', 'Fail'); + const maxWaitBlocks = 3; - expect( - xcmpQueueFailEvent != null, - '[Karura] xcmpQueue.FailEvent event is expected', - ).to.be.true; + // TODO + const xcmpQueueFailEvent = await waitEvent(helper.getApi(), maxWaitBlocks, 'xcmpQueue', 'Fail'); - const event = xcmpQueueFailEvent!.event; - const outcome = event.data[1] as XcmV2TraitsError; + expect( + xcmpQueueFailEvent != null, + '[Karura] xcmpQueue.FailEvent event is expected', + ).to.be.true; - expect( - outcome.isUntrustedReserveLocation, - '[Karura] The XCM error should be `UntrustedReserveLocation`', - ).to.be.true; - }); + const event = xcmpQueueFailEvent!.event; + const outcome = event.data[1] as XcmV2TraitsError; + + expect( + outcome.isUntrustedReserveLocation, + '[Karura] The XCM error should be `UntrustedReserveLocation`', + ).to.be.true; }); }); -describe_xcm('[XCM] Integration test: Exchanging QTZ with Moonriver', () => { +describeXcm('[XCM] Integration test: Exchanging QTZ with Moonriver', () => { // Quartz constants let quartzAlice: IKeyringPair; @@ -478,322 +460,327 @@ let balanceMovrTokenFinal: bigint; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { + await usingPlaygrounds(async (_helper, privateKey) => { const keyringEth = new Keyring({type: 'ethereum'}); const keyringSr25519 = new Keyring({type: 'sr25519'}); - quartzAlice = privateKeyWrapper('//Alice'); + quartzAlice = privateKey('//Alice'); randomAccountQuartz = generateKeyringPair(keyringSr25519); randomAccountMoonriver = generateKeyringPair(keyringEth); balanceForeignQtzTokenInit = 0n; }); - await usingApi( - async (api) => { + await usingPlaygrounds.atUrl(moonriverUrl, async (helper) => { + // TODO - // >>> Sponsoring Dorothy >>> - console.log('Sponsoring Dorothy.......'); - const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); - const events0 = await submitTransactionAsync(alithAccount, tx0); - const result0 = getGenericResult(events0); - expect(result0.success).to.be.true; - console.log('Sponsoring Dorothy.......DONE'); - // <<< Sponsoring Dorothy <<< + const api = helper.getApi(); - const sourceLocation: MultiLocation = api.createType( - 'MultiLocation', - { - parents: 1, - interior: {X1: {Parachain: QUARTZ_CHAIN}}, - }, - ); + // >>> Sponsoring Dorothy >>> + console.log('Sponsoring Dorothy.......'); + // const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); + // const events0 = await submitTransactionAsync(alithAccount, tx0); + // const result0 = getGenericResult(events0); + // expect(result0.success).to.be.true; + await helper.balance.transferToSubstrate(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n); + console.log('Sponsoring Dorothy.......DONE'); + // <<< Sponsoring Dorothy <<< - quartzAssetLocation = {XCM: sourceLocation}; - const existentialDeposit = 1; - const isSufficient = true; - const unitsPerSecond = '1'; - const numAssetsWeightHint = 0; + const sourceLocation: MultiLocation = api.createType( + 'MultiLocation', + { + parents: 1, + interior: {X1: {Parachain: QUARTZ_CHAIN}}, + }, + ); - const registerTx = api.tx.assetManager.registerForeignAsset( - quartzAssetLocation, - quartzAssetMetadata, - existentialDeposit, - isSufficient, - ); - console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); + quartzAssetLocation = {XCM: sourceLocation}; + const existentialDeposit = 1; + const isSufficient = true; + const unitsPerSecond = '1'; + const numAssetsWeightHint = 0; - const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( - quartzAssetLocation, - unitsPerSecond, - numAssetsWeightHint, - ); - console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); + const registerTx = api.tx.assetManager.registerForeignAsset( + quartzAssetLocation, + quartzAssetMetadata, + existentialDeposit, + isSufficient, + ); + console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); - const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); - console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); + const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( + quartzAssetLocation, + unitsPerSecond, + numAssetsWeightHint, + ); + console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); - // >>> Note motion preimage >>> - console.log('Note motion preimage.......'); - const encodedProposal = batchCall?.method.toHex() || ''; - const proposalHash = blake2AsHex(encodedProposal); - console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); - console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); - console.log('Encoded length %d', encodedProposal.length); + const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); + console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); - const tx1 = api.tx.democracy.notePreimage(encodedProposal); - const events1 = await submitTransactionAsync(baltatharAccount, tx1); - const result1 = getGenericResult(events1); - expect(result1.success).to.be.true; - console.log('Note motion preimage.......DONE'); - // <<< Note motion preimage <<< + // >>> Note motion preimage >>> + console.log('Note motion preimage.......'); + const encodedProposal = batchCall?.method.toHex() || ''; + const proposalHash = blake2AsHex(encodedProposal); + console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); + console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); + console.log('Encoded length %d', encodedProposal.length); - // >>> Propose external motion through council >>> - console.log('Propose external motion through council.......'); - const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); - const tx2 = api.tx.councilCollective.propose( - councilVotingThreshold, - externalMotion, - externalMotion.encodedLength, - ); - const events2 = await submitTransactionAsync(baltatharAccount, tx2); - const result2 = getGenericResult(events2); - expect(result2.success).to.be.true; + const tx1 = api.tx.democracy.notePreimage(encodedProposal); + const events1 = await submitTransactionAsync(baltatharAccount, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + console.log('Note motion preimage.......DONE'); + // <<< Note motion preimage <<< - const encodedMotion = externalMotion?.method.toHex() || ''; - const motionHash = blake2AsHex(encodedMotion); - console.log('Motion hash is %s', motionHash); + // >>> Propose external motion through council >>> + console.log('Propose external motion through council.......'); + const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); + const tx2 = api.tx.councilCollective.propose( + councilVotingThreshold, + externalMotion, + externalMotion.encodedLength, + ); + const events2 = await submitTransactionAsync(baltatharAccount, tx2); + const result2 = getGenericResult(events2); + expect(result2.success).to.be.true; - const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); - { - const events3 = await submitTransactionAsync(dorothyAccount, tx3); - const result3 = getGenericResult(events3); - expect(result3.success).to.be.true; - } - { - const events3 = await submitTransactionAsync(baltatharAccount, tx3); - const result3 = getGenericResult(events3); - expect(result3.success).to.be.true; - } + const encodedMotion = externalMotion?.method.toHex() || ''; + const motionHash = blake2AsHex(encodedMotion); + console.log('Motion hash is %s', motionHash); - const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); - const events4 = await submitTransactionAsync(dorothyAccount, tx4); - const result4 = getGenericResult(events4); - expect(result4.success).to.be.true; - console.log('Propose external motion through council.......DONE'); - // <<< Propose external motion through council <<< + const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); + { + const events3 = await submitTransactionAsync(dorothyAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + { + const events3 = await submitTransactionAsync(baltatharAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } - // >>> Fast track proposal through technical committee >>> - console.log('Fast track proposal through technical committee.......'); - const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); - const tx5 = api.tx.techCommitteeCollective.propose( - technicalCommitteeThreshold, - fastTrack, - fastTrack.encodedLength, - ); - const events5 = await submitTransactionAsync(alithAccount, tx5); - const result5 = getGenericResult(events5); - expect(result5.success).to.be.true; + const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); + const events4 = await submitTransactionAsync(dorothyAccount, tx4); + const result4 = getGenericResult(events4); + expect(result4.success).to.be.true; + console.log('Propose external motion through council.......DONE'); + // <<< Propose external motion through council <<< - const encodedFastTrack = fastTrack?.method.toHex() || ''; - const fastTrackHash = blake2AsHex(encodedFastTrack); - console.log('FastTrack hash is %s', fastTrackHash); + // >>> Fast track proposal through technical committee >>> + console.log('Fast track proposal through technical committee.......'); + const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); + const tx5 = api.tx.techCommitteeCollective.propose( + technicalCommitteeThreshold, + fastTrack, + fastTrack.encodedLength, + ); + const events5 = await submitTransactionAsync(alithAccount, tx5); + const result5 = getGenericResult(events5); + expect(result5.success).to.be.true; - const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; - const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); - { - const events6 = await submitTransactionAsync(baltatharAccount, tx6); - const result6 = getGenericResult(events6); - expect(result6.success).to.be.true; - } - { - const events6 = await submitTransactionAsync(alithAccount, tx6); - const result6 = getGenericResult(events6); - expect(result6.success).to.be.true; - } + const encodedFastTrack = fastTrack?.method.toHex() || ''; + const fastTrackHash = blake2AsHex(encodedFastTrack); + console.log('FastTrack hash is %s', fastTrackHash); - const tx7 = api.tx.techCommitteeCollective - .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); - const events7 = await submitTransactionAsync(baltatharAccount, tx7); - const result7 = getGenericResult(events7); - expect(result7.success).to.be.true; - console.log('Fast track proposal through technical committee.......DONE'); - // <<< Fast track proposal through technical committee <<< + const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; + const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); + { + const events6 = await submitTransactionAsync(baltatharAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + { + const events6 = await submitTransactionAsync(alithAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } - // >>> Referendum voting >>> - console.log('Referendum voting.......'); - const tx8 = api.tx.democracy.vote( - 0, - {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, - ); - const events8 = await submitTransactionAsync(dorothyAccount, tx8); - const result8 = getGenericResult(events8); - expect(result8.success).to.be.true; - console.log('Referendum voting.......DONE'); - // <<< Referendum voting <<< + const tx7 = api.tx.techCommitteeCollective + .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); + const events7 = await submitTransactionAsync(baltatharAccount, tx7); + const result7 = getGenericResult(events7); + expect(result7.success).to.be.true; + console.log('Fast track proposal through technical committee.......DONE'); + // <<< Fast track proposal through technical committee <<< - // >>> Acquire Quartz AssetId Info on Moonriver >>> - console.log('Acquire Quartz AssetId Info on Moonriver.......'); + // >>> Referendum voting >>> + console.log('Referendum voting.......'); + const tx8 = api.tx.democracy.vote( + 0, + {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, + ); + const events8 = await submitTransactionAsync(dorothyAccount, tx8); + const result8 = getGenericResult(events8); + expect(result8.success).to.be.true; + console.log('Referendum voting.......DONE'); + // <<< Referendum voting <<< - // Wait for the democracy execute - await waitNewBlocks(api, 5); + // >>> Acquire Quartz AssetId Info on Moonriver >>> + console.log('Acquire Quartz AssetId Info on Moonriver.......'); - assetId = (await api.query.assetManager.assetTypeId({ - XCM: sourceLocation, - })).toString(); + // Wait for the democracy execute + // await waitNewBlocks(api, 5); + await helper.wait.newBlocks(5); - console.log('QTZ asset ID is %s', assetId); - console.log('Acquire Quartz AssetId Info on Moonriver.......DONE'); - // >>> Acquire Quartz AssetId Info on Moonriver >>> + assetId = (await api.query.assetManager.assetTypeId({ + XCM: sourceLocation, + })).toString(); - // >>> Sponsoring random Account >>> - console.log('Sponsoring random Account.......'); - const tx10 = api.tx.balances.transfer(randomAccountMoonriver.address, 11_000_000_000_000_000_000n); - const events10 = await submitTransactionAsync(baltatharAccount, tx10); - const result10 = getGenericResult(events10); - expect(result10.success).to.be.true; - console.log('Sponsoring random Account.......DONE'); - // <<< Sponsoring random Account <<< + console.log('QTZ asset ID is %s', assetId); + console.log('Acquire Quartz AssetId Info on Moonriver.......DONE'); + // >>> Acquire Quartz AssetId Info on Moonriver >>> - [balanceMovrTokenInit] = await getBalance(api, [randomAccountMoonriver.address]); - }, - moonriverOptions(), - ); + // >>> Sponsoring random Account >>> + console.log('Sponsoring random Account.......'); + // const tx10 = api.tx.balances.transfer(randomAccountMoonriver.address, 11_000_000_000_000_000_000n); + // const events10 = await submitTransactionAsync(baltatharAccount, tx10); + // const result10 = getGenericResult(events10); + // expect(result10.success).to.be.true; + await helper.balance.transferToSubstrate(baltatharAccount, randomAccountMoonriver.address, 11_000_000_000_000_000_000n); + console.log('Sponsoring random Account.......DONE'); + // <<< Sponsoring random Account <<< - await usingApi(async (api) => { - const tx0 = api.tx.balances.transfer(randomAccountQuartz.address, 10n * TRANSFER_AMOUNT); - const events0 = await submitTransactionAsync(quartzAlice, tx0); - const result0 = getGenericResult(events0); - expect(result0.success).to.be.true; + // [balanceMovrTokenInit] = await getBalance(api, [randomAccountMoonriver.address]); + balanceMovrTokenInit = await helper.balance.getSubstrate(randomAccountMoonriver.address); + }); - [balanceQuartzTokenInit] = await getBalance(api, [randomAccountQuartz.address]); + await usingPlaygrounds(async (helper) => { + // const tx0 = api.tx.balances.transfer(randomAccountQuartz.address, 10n * TRANSFER_AMOUNT); + // const events0 = await submitTransactionAsync(quartzAlice, tx0); + // const result0 = getGenericResult(events0); + // expect(result0.success).to.be.true; + await helper.balance.transferToSubstrate(quartzAlice, randomAccountQuartz.address, 10n * TRANSFER_AMOUNT); + + // [balanceQuartzTokenInit] = await getBalance(api, [randomAccountQuartz.address]); + balanceQuartzTokenInit = await helper.balance.getSubstrate(randomAccountQuartz.address); }); }); - it('Should connect and send QTZ to Moonriver', async () => { - await usingApi(async (api) => { - const currencyId = { - NativeAssetId: 'Here', - }; - const dest = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: MOONRIVER_CHAIN}, - {AccountKey20: {network: 'Any', key: randomAccountMoonriver.address}}, - ], - }, + itSub('Should connect and send QTZ to Moonriver', async ({helper}) => { + const currencyId = { + NativeAssetId: 'Here', + }; + const dest = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: MOONRIVER_CHAIN}, + {AccountKey20: {network: 'Any', key: randomAccountMoonriver.address}}, + ], }, - }; - const amount = TRANSFER_AMOUNT; - const destWeight = 850000000; + }, + }; + const amount = TRANSFER_AMOUNT; + const destWeight = 850000000; - const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeight); - const events = await submitTransactionAsync(randomAccountQuartz, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transfer(currencyId, amount, dest, destWeight); + const events = await submitTransactionAsync(randomAccountQuartz, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccountQuartz.address]); - expect(balanceQuartzTokenMiddle < balanceQuartzTokenInit).to.be.true; + // [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccountQuartz.address]); + balanceQuartzTokenMiddle = await helper.balance.getSubstrate(randomAccountQuartz.address); + expect(balanceQuartzTokenMiddle < balanceQuartzTokenInit).to.be.true; - const transactionFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; - console.log('[Quartz -> Moonriver] transaction fees on Quartz: %s QTZ', bigIntToDecimals(transactionFees)); - expect(transactionFees > 0).to.be.true; - }); + const transactionFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; + console.log('[Quartz -> Moonriver] transaction fees on Quartz: %s QTZ', bigIntToDecimals(transactionFees)); + expect(transactionFees > 0).to.be.true; - await usingApi( - async (api) => { - await waitNewBlocks(api, 3); + await usingPlaygrounds.atUrl(moonriverUrl, async (helper) => { + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceMovrTokenMiddle] = await getBalance(api, [randomAccountMoonriver.address]); + // [balanceMovrTokenMiddle] = await getBalance(api, [randomAccountMoonriver.address]); + balanceMovrTokenMiddle = await helper.balance.getSubstrate(randomAccountMoonriver.address); - const movrFees = balanceMovrTokenInit - balanceMovrTokenMiddle; - console.log('[Quartz -> Moonriver] transaction fees on Moonriver: %s MOVR',bigIntToDecimals(movrFees)); - expect(movrFees == 0n).to.be.true; + const movrFees = balanceMovrTokenInit - balanceMovrTokenMiddle; + console.log('[Quartz -> Moonriver] transaction fees on Moonriver: %s MOVR',bigIntToDecimals(movrFees)); + expect(movrFees == 0n).to.be.true; - const qtzRandomAccountAsset = ( - await api.query.assets.account(assetId, randomAccountMoonriver.address) - ).toJSON()! as any; + // TODO + const qtzRandomAccountAsset = ( + await helper.getApi().query.assets.account(assetId, randomAccountMoonriver.address) + ).toJSON()! as any; - balanceForeignQtzTokenMiddle = BigInt(qtzRandomAccountAsset['balance']); - const qtzIncomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenInit; - console.log('[Quartz -> Moonriver] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); - expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - moonriverOptions(), - ); + balanceForeignQtzTokenMiddle = BigInt(qtzRandomAccountAsset['balance']); + const qtzIncomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenInit; + console.log('[Quartz -> Moonriver] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); + expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); }); - it('Should connect to Moonriver and send QTZ back', async () => { - await usingApi( - async (api) => { - const asset = { - V1: { - id: { - Concrete: { - parents: 1, - interior: { - X1: {Parachain: QUARTZ_CHAIN}, - }, + itSub('Should connect to Moonriver and send QTZ back', async ({helper}) => { + await usingPlaygrounds.atUrl(moonriverUrl, async (helper) => { + const asset = { + V1: { + id: { + Concrete: { + parents: 1, + interior: { + X1: {Parachain: QUARTZ_CHAIN}, }, }, - fun: { - Fungible: TRANSFER_AMOUNT, - }, }, - }; - const destination = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: QUARTZ_CHAIN}, - {AccountId32: {network: 'Any', id: randomAccountQuartz.addressRaw}}, - ], - }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + }; + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: QUARTZ_CHAIN}, + {AccountId32: {network: 'Any', id: randomAccountQuartz.addressRaw}}, + ], }, - }; - const destWeight = 50000000; + }, + }; + const destWeight = 50000000; - const tx = api.tx.xTokens.transferMultiasset(asset, destination, destWeight); - const events = await submitTransactionAsync(randomAccountMoonriver, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transferMultiasset(asset, destination, destWeight); + const events = await submitTransactionAsync(randomAccountMoonriver, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceMovrTokenFinal] = await getBalance(api, [randomAccountMoonriver.address]); + // [balanceMovrTokenFinal] = await getBalance(api, [randomAccountMoonriver.address]); + balanceMovrTokenFinal = await helper.balance.getSubstrate(randomAccountMoonriver.address); - const movrFees = balanceMovrTokenMiddle - balanceMovrTokenFinal; - console.log('[Moonriver -> Quartz] transaction fees on Moonriver: %s MOVR', bigIntToDecimals(movrFees)); - expect(movrFees > 0).to.be.true; + const movrFees = balanceMovrTokenMiddle - balanceMovrTokenFinal; + console.log('[Moonriver -> Quartz] transaction fees on Moonriver: %s MOVR', bigIntToDecimals(movrFees)); + expect(movrFees > 0).to.be.true; - const qtzRandomAccountAsset = ( - await api.query.assets.account(assetId, randomAccountMoonriver.address) - ).toJSON()! as any; + const qtzRandomAccountAsset = ( + await helper.getApi().query.assets.account(assetId, randomAccountMoonriver.address) + ).toJSON()! as any; - expect(qtzRandomAccountAsset).to.be.null; + expect(qtzRandomAccountAsset).to.be.null; - balanceForeignQtzTokenFinal = 0n; + balanceForeignQtzTokenFinal = 0n; - const qtzOutcomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenFinal; - console.log('[Quartz -> Moonriver] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); - expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - moonriverOptions(), - ); + const qtzOutcomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenFinal; + console.log('[Quartz -> Moonriver] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); + expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceQuartzTokenFinal] = await getBalance(api, [randomAccountQuartz.address]); - const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; - expect(actuallyDelivered > 0).to.be.true; + // [balanceQuartzTokenFinal] = await getBalance(api, [randomAccountQuartz.address]); + balanceQuartzTokenFinal = await helper.balance.getSubstrate(randomAccountQuartz.address); + const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; - console.log('[Moonriver -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); + console.log('[Moonriver -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); - const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; - console.log('[Moonriver -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); - expect(qtzFees == 0n).to.be.true; - }); + const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Moonriver -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees == 0n).to.be.true; }); }); --- a/tests/src/xcm/xcmUnique.test.ts +++ b/tests/src/xcm/xcmUnique.test.ts @@ -14,23 +14,16 @@ // 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, Keyring} from '@polkadot/api'; -import {ApiOptions} from '@polkadot/api/types'; +import {Keyring} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; -import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; -import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../deprecated-helpers/helpers'; +import {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult, generateKeyringPair, waitEvent, bigIntToDecimals} from '../deprecated-helpers/helpers'; import {MultiLocation} from '@polkadot/types/interfaces'; import {blake2AsHex} from '@polkadot/util-crypto'; -import waitNewBlocks from '../substrate/wait-new-blocks'; import getBalance from '../substrate/get-balance'; import {XcmV2TraitsError, XcmV2TraitsOutcome} from '../interfaces'; +import {itSub, expect, describeXcm, usingPlaygrounds} from '../util/playgrounds'; -chai.use(chaiAsPromised); -const expect = chai.expect; - const UNIQUE_CHAIN = 2037; const ACALA_CHAIN = 2000; const MOONBEAM_CHAIN = 2004; @@ -39,29 +32,15 @@ const ACALA_PORT = 9946; const MOONBEAM_PORT = 9947; +const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT; +const acalaUrl = 'ws://127.0.0.1:' + ACALA_PORT; +const moonbeamUrl = 'ws://127.0.0.1:' + MOONBEAM_PORT; + const ACALA_DECIMALS = 12; const TRANSFER_AMOUNT = 2000000000000000000000000n; -function parachainApiOptions(port: number): ApiOptions { - return { - provider: new WsProvider('ws://127.0.0.1:' + port.toString()), - }; -} - -function acalaOptions(): ApiOptions { - return parachainApiOptions(ACALA_PORT); -} - -function moonbeamOptions(): ApiOptions { - return parachainApiOptions(MOONBEAM_PORT); -} - -function relayOptions(): ApiOptions { - return parachainApiOptions(RELAY_PORT); -} - -describe_xcm('[XCM] Integration test: Exchanging tokens with Acala', () => { +describeXcm('[XCM] Integration test: Exchanging tokens with Acala', () => { let alice: IKeyringPair; let randomAccount: IKeyringPair; @@ -76,233 +55,235 @@ let balanceUniqueForeignTokenFinal: bigint; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { + await usingPlaygrounds(async (_helper, privateKey) => { const keyringSr25519 = new Keyring({type: 'sr25519'}); - alice = privateKeyWrapper('//Alice'); + alice = privateKey('//Alice'); randomAccount = generateKeyringPair(keyringSr25519); }); // Acala side - await usingApi( - async (api) => { - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: UNIQUE_CHAIN, - }, - ], - }, - }; + await usingPlaygrounds.atUrl(acalaUrl, async (helper) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: UNIQUE_CHAIN, + }, + ], + }, + }; - const metadata = { - name: 'UNQ', - symbol: 'UNQ', - decimals: 18, - minimalBalance: 1, - }; + 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; + // TODO + const tx = helper.getApi().tx.assetRegistry.registerForeignAsset(destination, metadata); + const sudoTx = helper.getApi().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; + // 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; + await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n); - [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]); - { - const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; - balanceUniqueForeignTokenInit = BigInt(free); - } - }, - acalaOptions(), - ); + // [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]); + balanceAcalaTokenInit = await helper.balance.getSubstrate(randomAccount.address); + { + // TODO + const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenInit = BigInt(free); + } + }); // 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; + await usingPlaygrounds(async (helper) => { + // 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; + await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT); - [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]); + // [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]); + balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address); }); }); - it('Should connect and send UNQ to Acala', async () => { + itSub('Should connect and send UNQ to Acala', async ({helper}) => { // Unique side - await usingApi(async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: ACALA_CHAIN, + }, + ], + }, + }; - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: ACALA_CHAIN, - }, - ], + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, }, - }; + }, + }; - const beneficiary = { - V0: { - X1: { - AccountId32: { - network: 'Any', - id: randomAccount.addressRaw, + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', }, }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, }, - }; + ], + }; - const assets = { - V1: [ - { - id: { - Concrete: { - parents: 0, - interior: 'Here', - }, - }, - fun: { - Fungible: TRANSFER_AMOUNT, - }, - }, - ], - }; + const feeAssetItem = 0; - const feeAssetItem = 0; - - const weightLimit = { - Limited: 5000000000, - }; + 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; + // TODO + const tx = helper.getApi().tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]); + // [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]); + balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address); - const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; - console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); - expect(unqFees > 0n).to.be.true; - }); + const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; + console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees > 0n).to.be.true; // Acala side - await usingApi( - async (api) => { - await waitNewBlocks(api, 3); - const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; - balanceUniqueForeignTokenMiddle = BigInt(free); + await usingPlaygrounds.atUrl(acalaUrl, async (helper) => { + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]); + // TODO + const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenMiddle = BigInt(free); - const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle; - const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit; + // [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]); + balanceAcalaTokenMiddle = await helper.balance.getSubstrate(randomAccount.address); - console.log( - '[Unique -> Acala] transaction fees on Acala: %s ACA', - bigIntToDecimals(acaFees, ACALA_DECIMALS), - ); - console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); - expect(acaFees == 0n).to.be.true; - expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - acalaOptions(), - ); + const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle; + const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit; + + console.log( + '[Unique -> Acala] transaction fees on Acala: %s ACA', + bigIntToDecimals(acaFees, ACALA_DECIMALS), + ); + console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); + expect(acaFees == 0n).to.be.true; + expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); }); - it('Should connect to Acala and send UNQ back', async () => { + itSub('Should connect to Acala and send UNQ back', async ({helper}) => { // Acala side - await usingApi( - async (api) => { - const destination = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: UNIQUE_CHAIN}, - { - AccountId32: { - network: 'Any', - id: randomAccount.addressRaw, - }, + await usingPlaygrounds.atUrl(acalaUrl, async (helper) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, }, - ], - }, + }, + ], }, - }; + }, + }; - const id = { - ForeignAsset: 0, - }; + const id = { + ForeignAsset: 0, + }; - const destWeight = 50000000; + const destWeight = 50000000; - const tx = api.tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight); - const events = await submitTransactionAsync(randomAccount, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transfer(id as any, TRANSFER_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, id)).toJSON() as any; - balanceUniqueForeignTokenFinal = BigInt(free); - } + // [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]); + balanceAcalaTokenFinal = await helper.balance.getSubstrate(randomAccount.address); + { + // TODO + const {free} = (await helper.getApi().query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any; + balanceUniqueForeignTokenFinal = BigInt(free); + } - const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal; - const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal; + const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal; + const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal; - console.log( - '[Acala -> Unique] transaction fees on Acala: %s ACA', - bigIntToDecimals(acaFees, ACALA_DECIMALS), - ); - console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); + console.log( + '[Acala -> Unique] transaction fees on Acala: %s ACA', + bigIntToDecimals(acaFees, ACALA_DECIMALS), + ); + console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); - expect(acaFees > 0).to.be.true; - expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - acalaOptions(), - ); + expect(acaFees > 0).to.be.true; + expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); - // Unique side - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]); - const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; - expect(actuallyDelivered > 0).to.be.true; + // [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]); + balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccount.address); + const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; - console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); + console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); - const unqFees = TRANSFER_AMOUNT - actuallyDelivered; - console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); - expect(unqFees == 0n).to.be.true; - }); + const unqFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees == 0n).to.be.true; }); }); // These tests are relevant only when the foreign asset pallet is disabled -describe_xcm('[XCM] Integration test: Unique rejects non-native tokens', () => { +describeXcm('[XCM] Integration test: Unique rejects non-native tokens', () => { let alice: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); + await usingPlaygrounds(async (_helper, privateKey) => { + alice = privateKey('//Alice'); }); }); - it('Unique rejects tokens from the Relay', async () => { - await usingApi(async (api) => { + itSub('Unique rejects tokens from the Relay', async ({helper}) => { + await usingPlaygrounds.atUrl(relayUrl, async (helper) => { const destination = { V1: { parents: 0, @@ -346,44 +327,45 @@ Limited: 5_000_000_000, }; - const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + // TODO + const tx = helper.getApi().tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, relayOptions()); + }); - await usingApi(async api => { - const maxWaitBlocks = 3; - const dmpQueueExecutedDownward = await waitEvent( - api, - maxWaitBlocks, - 'dmpQueue', - 'ExecutedDownward', - ); + const maxWaitBlocks = 3; - expect( - dmpQueueExecutedDownward != null, - '[Relay] dmpQueue.ExecutedDownward event is expected', - ).to.be.true; + // TODO + const dmpQueueExecutedDownward = await waitEvent( + helper.getApi(), + maxWaitBlocks, + 'dmpQueue', + 'ExecutedDownward', + ); - const event = dmpQueueExecutedDownward!.event; - const outcome = event.data[1] as XcmV2TraitsOutcome; + expect( + dmpQueueExecutedDownward != null, + '[Relay] dmpQueue.ExecutedDownward event is expected', + ).to.be.true; - expect( - outcome.isIncomplete, - '[Relay] The outcome of the XCM should be `Incomplete`', - ).to.be.true; + const event = dmpQueueExecutedDownward!.event; + const outcome = event.data[1] as XcmV2TraitsOutcome; + + expect( + outcome.isIncomplete, + '[Relay] The outcome of the XCM should be `Incomplete`', + ).to.be.true; - const incomplete = outcome.asIncomplete; - expect( - incomplete[1].toString() == 'AssetNotFound', - '[Relay] The XCM error should be `AssetNotFound`', - ).to.be.true; - }); + const incomplete = outcome.asIncomplete; + expect( + incomplete[1].toString() == 'AssetNotFound', + '[Relay] The XCM error should be `AssetNotFound`', + ).to.be.true; }); - it('Unique rejects ACA tokens from Acala', async () => { - await usingApi(async (api) => { + itSub('Unique rejects ACA tokens from Acala', async ({helper}) => { + await usingPlaygrounds.atUrl(acalaUrl, async (helper) => { const destination = { V1: { parents: 1, @@ -407,33 +389,34 @@ const destWeight = 50000000; - const tx = api.tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); + // TODO + const tx = helper.getApi().tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); expect(result.success).to.be.true; - }, acalaOptions()); + }); - await usingApi(async api => { - const maxWaitBlocks = 3; - const xcmpQueueFailEvent = await waitEvent(api, maxWaitBlocks, 'xcmpQueue', 'Fail'); + const maxWaitBlocks = 3; - expect( - xcmpQueueFailEvent != null, - '[Acala] xcmpQueue.FailEvent event is expected', - ).to.be.true; + // TODO + const xcmpQueueFailEvent = await waitEvent(helper.getApi(), maxWaitBlocks, 'xcmpQueue', 'Fail'); - const event = xcmpQueueFailEvent!.event; - const outcome = event.data[1] as XcmV2TraitsError; + expect( + xcmpQueueFailEvent != null, + '[Acala] xcmpQueue.FailEvent event is expected', + ).to.be.true; + + const event = xcmpQueueFailEvent!.event; + const outcome = event.data[1] as XcmV2TraitsError; - expect( - outcome.isUntrustedReserveLocation, - '[Acala] The XCM error should be `UntrustedReserveLocation`', - ).to.be.true; - }); + expect( + outcome.isUntrustedReserveLocation, + '[Acala] The XCM error should be `UntrustedReserveLocation`', + ).to.be.true; }); }); -describe_xcm('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => { +describeXcm('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => { // Unique constants let uniqueAlice: IKeyringPair; @@ -478,322 +461,327 @@ let balanceGlmrTokenFinal: bigint; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { + await usingPlaygrounds(async (_helper, privateKey) => { const keyringEth = new Keyring({type: 'ethereum'}); const keyringSr25519 = new Keyring({type: 'sr25519'}); - uniqueAlice = privateKeyWrapper('//Alice'); + uniqueAlice = privateKey('//Alice'); randomAccountUnique = generateKeyringPair(keyringSr25519); randomAccountMoonbeam = generateKeyringPair(keyringEth); balanceForeignUnqTokenInit = 0n; }); - await usingApi( - async (api) => { + await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => { + // TODO + + const api = helper.getApi(); - // >>> Sponsoring Dorothy >>> - console.log('Sponsoring Dorothy.......'); - const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); - const events0 = await submitTransactionAsync(alithAccount, tx0); - const result0 = getGenericResult(events0); - expect(result0.success).to.be.true; - console.log('Sponsoring Dorothy.......DONE'); - // <<< Sponsoring Dorothy <<< + // >>> Sponsoring Dorothy >>> + console.log('Sponsoring Dorothy.......'); + // const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); + // const events0 = await submitTransactionAsync(alithAccount, tx0); + // const result0 = getGenericResult(events0); + // expect(result0.success).to.be.true; + await helper.balance.transferToSubstrate(alithAccount, dorothyAccount.address, 11_000_000_000_000_000_000n); + console.log('Sponsoring Dorothy.......DONE'); + // <<< Sponsoring Dorothy <<< - const sourceLocation: MultiLocation = api.createType( - 'MultiLocation', - { - parents: 1, - interior: {X1: {Parachain: UNIQUE_CHAIN}}, - }, - ); + const sourceLocation: MultiLocation = api.createType( + 'MultiLocation', + { + parents: 1, + interior: {X1: {Parachain: UNIQUE_CHAIN}}, + }, + ); - uniqueAssetLocation = {XCM: sourceLocation}; - const existentialDeposit = 1; - const isSufficient = true; - const unitsPerSecond = '1'; - const numAssetsWeightHint = 0; + uniqueAssetLocation = {XCM: sourceLocation}; + const existentialDeposit = 1; + const isSufficient = true; + const unitsPerSecond = '1'; + const numAssetsWeightHint = 0; - const registerTx = api.tx.assetManager.registerForeignAsset( - uniqueAssetLocation, - uniqueAssetMetadata, - existentialDeposit, - isSufficient, - ); - console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); + const registerTx = api.tx.assetManager.registerForeignAsset( + uniqueAssetLocation, + uniqueAssetMetadata, + existentialDeposit, + isSufficient, + ); + console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); - const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( - uniqueAssetLocation, - unitsPerSecond, - numAssetsWeightHint, - ); - console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); + const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( + uniqueAssetLocation, + unitsPerSecond, + numAssetsWeightHint, + ); + console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); - const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); - console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); + const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); + console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); - // >>> Note motion preimage >>> - console.log('Note motion preimage.......'); - const encodedProposal = batchCall?.method.toHex() || ''; - const proposalHash = blake2AsHex(encodedProposal); - console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); - console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); - console.log('Encoded length %d', encodedProposal.length); + // >>> Note motion preimage >>> + console.log('Note motion preimage.......'); + const encodedProposal = batchCall?.method.toHex() || ''; + const proposalHash = blake2AsHex(encodedProposal); + console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); + console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); + console.log('Encoded length %d', encodedProposal.length); - const tx1 = api.tx.democracy.notePreimage(encodedProposal); - const events1 = await submitTransactionAsync(baltatharAccount, tx1); - const result1 = getGenericResult(events1); - expect(result1.success).to.be.true; - console.log('Note motion preimage.......DONE'); - // <<< Note motion preimage <<< + const tx1 = api.tx.democracy.notePreimage(encodedProposal); + const events1 = await submitTransactionAsync(baltatharAccount, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + console.log('Note motion preimage.......DONE'); + // <<< Note motion preimage <<< - // >>> Propose external motion through council >>> - console.log('Propose external motion through council.......'); - const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); - const tx2 = api.tx.councilCollective.propose( - councilVotingThreshold, - externalMotion, - externalMotion.encodedLength, - ); - const events2 = await submitTransactionAsync(baltatharAccount, tx2); - const result2 = getGenericResult(events2); - expect(result2.success).to.be.true; + // >>> Propose external motion through council >>> + console.log('Propose external motion through council.......'); + const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); + const tx2 = api.tx.councilCollective.propose( + councilVotingThreshold, + externalMotion, + externalMotion.encodedLength, + ); + const events2 = await submitTransactionAsync(baltatharAccount, tx2); + const result2 = getGenericResult(events2); + expect(result2.success).to.be.true; - const encodedMotion = externalMotion?.method.toHex() || ''; - const motionHash = blake2AsHex(encodedMotion); - console.log('Motion hash is %s', motionHash); + const encodedMotion = externalMotion?.method.toHex() || ''; + const motionHash = blake2AsHex(encodedMotion); + console.log('Motion hash is %s', motionHash); - const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); - { - const events3 = await submitTransactionAsync(dorothyAccount, tx3); - const result3 = getGenericResult(events3); - expect(result3.success).to.be.true; - } - { - const events3 = await submitTransactionAsync(baltatharAccount, tx3); - const result3 = getGenericResult(events3); - expect(result3.success).to.be.true; - } + const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); + { + const events3 = await submitTransactionAsync(dorothyAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + { + const events3 = await submitTransactionAsync(baltatharAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } - const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); - const events4 = await submitTransactionAsync(dorothyAccount, tx4); - const result4 = getGenericResult(events4); - expect(result4.success).to.be.true; - console.log('Propose external motion through council.......DONE'); - // <<< Propose external motion through council <<< + const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); + const events4 = await submitTransactionAsync(dorothyAccount, tx4); + const result4 = getGenericResult(events4); + expect(result4.success).to.be.true; + console.log('Propose external motion through council.......DONE'); + // <<< Propose external motion through council <<< - // >>> Fast track proposal through technical committee >>> - console.log('Fast track proposal through technical committee.......'); - const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); - const tx5 = api.tx.techCommitteeCollective.propose( - technicalCommitteeThreshold, - fastTrack, - fastTrack.encodedLength, - ); - const events5 = await submitTransactionAsync(alithAccount, tx5); - const result5 = getGenericResult(events5); - expect(result5.success).to.be.true; + // >>> Fast track proposal through technical committee >>> + console.log('Fast track proposal through technical committee.......'); + const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); + const tx5 = api.tx.techCommitteeCollective.propose( + technicalCommitteeThreshold, + fastTrack, + fastTrack.encodedLength, + ); + const events5 = await submitTransactionAsync(alithAccount, tx5); + const result5 = getGenericResult(events5); + expect(result5.success).to.be.true; - const encodedFastTrack = fastTrack?.method.toHex() || ''; - const fastTrackHash = blake2AsHex(encodedFastTrack); - console.log('FastTrack hash is %s', fastTrackHash); + const encodedFastTrack = fastTrack?.method.toHex() || ''; + const fastTrackHash = blake2AsHex(encodedFastTrack); + console.log('FastTrack hash is %s', fastTrackHash); - const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; - const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); - { - const events6 = await submitTransactionAsync(baltatharAccount, tx6); - const result6 = getGenericResult(events6); - expect(result6.success).to.be.true; - } - { - const events6 = await submitTransactionAsync(alithAccount, tx6); - const result6 = getGenericResult(events6); - expect(result6.success).to.be.true; - } + const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; + const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); + { + const events6 = await submitTransactionAsync(baltatharAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + { + const events6 = await submitTransactionAsync(alithAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } - const tx7 = api.tx.techCommitteeCollective - .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); - const events7 = await submitTransactionAsync(baltatharAccount, tx7); - const result7 = getGenericResult(events7); - expect(result7.success).to.be.true; - console.log('Fast track proposal through technical committee.......DONE'); - // <<< Fast track proposal through technical committee <<< + const tx7 = api.tx.techCommitteeCollective + .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); + const events7 = await submitTransactionAsync(baltatharAccount, tx7); + const result7 = getGenericResult(events7); + expect(result7.success).to.be.true; + console.log('Fast track proposal through technical committee.......DONE'); + // <<< Fast track proposal through technical committee <<< - // >>> Referendum voting >>> - console.log('Referendum voting.......'); - const tx8 = api.tx.democracy.vote( - 0, - {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, - ); - const events8 = await submitTransactionAsync(dorothyAccount, tx8); - const result8 = getGenericResult(events8); - expect(result8.success).to.be.true; - console.log('Referendum voting.......DONE'); - // <<< Referendum voting <<< + // >>> Referendum voting >>> + console.log('Referendum voting.......'); + const tx8 = api.tx.democracy.vote( + 0, + {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, + ); + const events8 = await submitTransactionAsync(dorothyAccount, tx8); + const result8 = getGenericResult(events8); + expect(result8.success).to.be.true; + console.log('Referendum voting.......DONE'); + // <<< Referendum voting <<< - // >>> Acquire Unique AssetId Info on Moonbeam >>> - console.log('Acquire Unique AssetId Info on Moonbeam.......'); + // >>> Acquire Unique AssetId Info on Moonbeam >>> + console.log('Acquire Unique AssetId Info on Moonbeam.......'); - // Wait for the democracy execute - await waitNewBlocks(api, 5); + // Wait for the democracy execute + // await waitNewBlocks(api, 5); + await helper.wait.newBlocks(5); - assetId = (await api.query.assetManager.assetTypeId({ - XCM: sourceLocation, - })).toString(); + assetId = (await api.query.assetManager.assetTypeId({ + XCM: sourceLocation, + })).toString(); - console.log('UNQ asset ID is %s', assetId); - console.log('Acquire Unique AssetId Info on Moonbeam.......DONE'); - // >>> Acquire Unique AssetId Info on Moonbeam >>> + console.log('UNQ asset ID is %s', assetId); + console.log('Acquire Unique AssetId Info on Moonbeam.......DONE'); + // >>> Acquire Unique AssetId Info on Moonbeam >>> - // >>> Sponsoring random Account >>> - console.log('Sponsoring random Account.......'); - const tx10 = api.tx.balances.transfer(randomAccountMoonbeam.address, 11_000_000_000_000_000_000n); - const events10 = await submitTransactionAsync(baltatharAccount, tx10); - const result10 = getGenericResult(events10); - expect(result10.success).to.be.true; - console.log('Sponsoring random Account.......DONE'); - // <<< Sponsoring random Account <<< + // >>> Sponsoring random Account >>> + console.log('Sponsoring random Account.......'); + // const tx10 = api.tx.balances.transfer(randomAccountMoonbeam.address, 11_000_000_000_000_000_000n); + // const events10 = await submitTransactionAsync(baltatharAccount, tx10); + // const result10 = getGenericResult(events10); + // expect(result10.success).to.be.true; + await helper.balance.transferToSubstrate(baltatharAccount, randomAccountMoonbeam.address, 11_000_000_000_000_000_000n); + console.log('Sponsoring random Account.......DONE'); + // <<< Sponsoring random Account <<< - [balanceGlmrTokenInit] = await getBalance(api, [randomAccountMoonbeam.address]); - }, - moonbeamOptions(), - ); + [balanceGlmrTokenInit] = await getBalance(api, [randomAccountMoonbeam.address]); + }); - await usingApi(async (api) => { - const tx0 = api.tx.balances.transfer(randomAccountUnique.address, 10n * TRANSFER_AMOUNT); - const events0 = await submitTransactionAsync(uniqueAlice, tx0); - const result0 = getGenericResult(events0); - expect(result0.success).to.be.true; + await usingPlaygrounds(async (helper) => { + // const tx0 = api.tx.balances.transfer(randomAccountUnique.address, 10n * TRANSFER_AMOUNT); + // const events0 = await submitTransactionAsync(uniqueAlice, tx0); + // const result0 = getGenericResult(events0); + // expect(result0.success).to.be.true; + await helper.balance.transferToSubstrate(uniqueAlice, randomAccountUnique.address, 10n * TRANSFER_AMOUNT); - [balanceUniqueTokenInit] = await getBalance(api, [randomAccountUnique.address]); + // [balanceUniqueTokenInit] = await getBalance(api, [randomAccountUnique.address]); + balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccountUnique.address); }); }); - it('Should connect and send UNQ to Moonbeam', async () => { - await usingApi(async (api) => { - const currencyId = { - NativeAssetId: 'Here', - }; - const dest = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: MOONBEAM_CHAIN}, - {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}}, - ], - }, + itSub('Should connect and send UNQ to Moonbeam', async ({helper}) => { + const currencyId = { + NativeAssetId: 'Here', + }; + const dest = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: MOONBEAM_CHAIN}, + {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}}, + ], }, - }; - const amount = TRANSFER_AMOUNT; - const destWeight = 850000000; + }, + }; + const amount = TRANSFER_AMOUNT; + const destWeight = 850000000; - const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeight); - const events = await submitTransactionAsync(randomAccountUnique, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transfer(currencyId, amount, dest, destWeight); + const events = await submitTransactionAsync(randomAccountUnique, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccountUnique.address]); - expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true; + // [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccountUnique.address]); + balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccountUnique.address); + expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true; - const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; - console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', bigIntToDecimals(transactionFees)); - expect(transactionFees > 0).to.be.true; - }); + const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; + console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', bigIntToDecimals(transactionFees)); + expect(transactionFees > 0).to.be.true; - await usingApi( - async (api) => { - await waitNewBlocks(api, 3); + await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => { + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceGlmrTokenMiddle] = await getBalance(api, [randomAccountMoonbeam.address]); + // [balanceGlmrTokenMiddle] = await getBalance(api, [randomAccountMoonbeam.address]); + balanceGlmrTokenMiddle = await helper.balance.getSubstrate(randomAccountMoonbeam.address); - const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle; - console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); - expect(glmrFees == 0n).to.be.true; + const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle; + console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); + expect(glmrFees == 0n).to.be.true; - const unqRandomAccountAsset = ( - await api.query.assets.account(assetId, randomAccountMoonbeam.address) - ).toJSON()! as any; + // TODO + const unqRandomAccountAsset = ( + await helper.getApi().query.assets.account(assetId, randomAccountMoonbeam.address) + ).toJSON()! as any; - balanceForeignUnqTokenMiddle = BigInt(unqRandomAccountAsset['balance']); - const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit; - console.log('[Unique -> Moonbeam] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); - expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - moonbeamOptions(), - ); + balanceForeignUnqTokenMiddle = BigInt(unqRandomAccountAsset['balance']); + const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit; + console.log('[Unique -> Moonbeam] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); + expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); }); - it('Should connect to Moonbeam and send UNQ back', async () => { - await usingApi( - async (api) => { - const asset = { - V1: { - id: { - Concrete: { - parents: 1, - interior: { - X1: {Parachain: UNIQUE_CHAIN}, - }, + itSub('Should connect to Moonbeam and send UNQ back', async ({helper}) => { + await usingPlaygrounds.atUrl(moonbeamUrl, async (helper) => { + const asset = { + V1: { + id: { + Concrete: { + parents: 1, + interior: { + X1: {Parachain: UNIQUE_CHAIN}, }, }, - fun: { - Fungible: TRANSFER_AMOUNT, - }, }, - }; - const destination = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: UNIQUE_CHAIN}, - {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}}, - ], - }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + }; + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}}, + ], }, - }; - const destWeight = 50000000; + }, + }; + const destWeight = 50000000; - const tx = api.tx.xTokens.transferMultiasset(asset, destination, destWeight); - const events = await submitTransactionAsync(randomAccountMoonbeam, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + // TODO + const tx = helper.getApi().tx.xTokens.transferMultiasset(asset, destination, destWeight); + const events = await submitTransactionAsync(randomAccountMoonbeam, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; - [balanceGlmrTokenFinal] = await getBalance(api, [randomAccountMoonbeam.address]); + // [balanceGlmrTokenFinal] = await getBalance(api, [randomAccountMoonbeam.address]); + balanceGlmrTokenFinal = await helper.balance.getSubstrate(randomAccountMoonbeam.address); - const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal; - console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); - expect(glmrFees > 0).to.be.true; + const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal; + console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); + expect(glmrFees > 0).to.be.true; - const unqRandomAccountAsset = ( - await api.query.assets.account(assetId, randomAccountMoonbeam.address) - ).toJSON()! as any; + // TODO + const unqRandomAccountAsset = ( + await helper.getApi().query.assets.account(assetId, randomAccountMoonbeam.address) + ).toJSON()! as any; - expect(unqRandomAccountAsset).to.be.null; + expect(unqRandomAccountAsset).to.be.null; - balanceForeignUnqTokenFinal = 0n; + balanceForeignUnqTokenFinal = 0n; - const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal; - console.log('[Unique -> Moonbeam] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); - expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; - }, - moonbeamOptions(), - ); + const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal; + console.log('[Unique -> Moonbeam] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); + expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }); - await usingApi(async (api) => { - await waitNewBlocks(api, 3); + // await waitNewBlocks(api, 3); + await helper.wait.newBlocks(3); - [balanceUniqueTokenFinal] = await getBalance(api, [randomAccountUnique.address]); - const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; - expect(actuallyDelivered > 0).to.be.true; + // [balanceUniqueTokenFinal] = await getBalance(api, [randomAccountUnique.address]); + balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccountUnique.address); + const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; - console.log('[Moonbeam -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); + console.log('[Moonbeam -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); - const unqFees = TRANSFER_AMOUNT - actuallyDelivered; - console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); - expect(unqFees == 0n).to.be.true; - }); + const unqFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees == 0n).to.be.true; }); });