git.delta.rocks / unique-network / refs/commits / 681fe40c30ae

difftreelog

refactor use playgrounds in opal xcm tests

Daniel Shiposha2022-10-11parent: #7921115.patch.diff
in: master

1 file changed

modifiedtests/src/xcm/xcmOpal.test.tsdiffbeforeafterboth
before · tests/src/xcm/xcmOpal.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {executeTransaction} from './../substrate/substrate-api';19import {bigIntToDecimals, getGenericResult, paraSiblingSovereignAccount} from './../deprecated-helpers/helpers';20import getBalance from './../substrate/get-balance';21import {itSub, expect, describeXcm, usingPlaygrounds} from '../util/playgrounds';2223const STATEMINE_CHAIN = 1000;24const UNIQUE_CHAIN = 2095;2526const RELAY_PORT = '9844';27const STATEMINE_PORT = '9948';2829const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT;30const statemineUrl = 'ws://127.0.0.1:' + STATEMINE_PORT;3132const STATEMINE_PALLET_INSTANCE = 50;33const ASSET_ID = 100;34const ASSET_METADATA_DECIMALS = 18;35const ASSET_METADATA_NAME = 'USDT';36const ASSET_METADATA_DESCRIPTION = 'USDT';37const ASSET_METADATA_MINIMAL_BALANCE = 1n;3839const WESTMINT_DECIMALS = 12;4041const TRANSFER_AMOUNT = 1_000_000_000_000_000_000n;4243// 10,000.00 (ten thousands) USDT44const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; 4546describeXcm('[XCM] Integration test: Exchanging USDT with Westmint', () => {47  let alice: IKeyringPair;48  let bob: IKeyringPair;49  50  let balanceStmnBefore: bigint;51  let balanceStmnAfter: bigint;5253  let balanceOpalBefore: bigint;54  let balanceOpalAfter: bigint;55  let balanceOpalFinal: bigint;5657  let balanceBobBefore: bigint;58  let balanceBobAfter: bigint;59  let balanceBobFinal: bigint;6061  let balanceBobRelayTokenBefore: bigint;62  let balanceBobRelayTokenAfter: bigint;636465  before(async () => {66    await usingPlaygrounds(async (_helper, privateKey) => {67      alice = privateKey('//Alice');68      bob = privateKey('//Bob'); // funds donor69    });7071    await usingPlaygrounds.atUrl(statemineUrl, async (helper) => {72      const api = helper.getApi();7374      // 350.00 (three hundred fifty) DOT75      const fundingAmount = 3_500_000_000_000; 7677      const tx = api.tx.assets.create(ASSET_ID, alice.addressRaw, ASSET_METADATA_MINIMAL_BALANCE);78      const events = await executeTransaction(api, alice, tx);79      const result = getGenericResult(events);80      expect(result.success).to.be.true;8182      // set metadata83      const tx2 = api.tx.assets.setMetadata(ASSET_ID, ASSET_METADATA_NAME, ASSET_METADATA_DESCRIPTION, ASSET_METADATA_DECIMALS);84      const events2 = await executeTransaction(api, alice, tx2);85      const result2 = getGenericResult(events2);86      expect(result2.success).to.be.true;8788      // mint some amount of asset89      const tx3 = api.tx.assets.mint(ASSET_ID, alice.addressRaw, ASSET_AMOUNT);90      const events3 = await executeTransaction(api, alice, tx3);91      const result3 = getGenericResult(events3);92      expect(result3.success).to.be.true;9394      // funding parachain sovereing account (Parachain: 2095)95      const parachainSovereingAccount = await paraSiblingSovereignAccount(UNIQUE_CHAIN);96      const tx4 = api.tx.balances.transfer(parachainSovereingAccount, fundingAmount);97      const events4 = await executeTransaction(api, bob, tx4);98      const result4 = getGenericResult(events4);99      expect(result4.success).to.be.true;100101    });102103104    await usingPlaygrounds(async (helper) => {105      const location = {106        V1: {107          parents: 1,108          interior: {X3: [109            {110              Parachain: STATEMINE_CHAIN,111            },112            {113              PalletInstance: STATEMINE_PALLET_INSTANCE,114            },115            {116              GeneralIndex: ASSET_ID,117            },118          ]},119        },120      };121122      const metadata =123      {124        name: ASSET_ID,125        symbol: ASSET_METADATA_NAME,126        decimals: ASSET_METADATA_DECIMALS,127        minimalBalance: ASSET_METADATA_MINIMAL_BALANCE,128      };129      await helper.getSudo().foreignAssets.register(alice, alice.address, location, metadata);130      // const tx = api.tx.foreignAssets.registerForeignAsset(alice.addressRaw, location, metadata);131      // const sudoTx = api.tx.sudo.sudo(tx as any);132      // const events = await executeTransaction(api, alice, sudoTx);133      // const result = getGenericResult(events);134      // expect(result.success).to.be.true;135136      // [balanceOpalBefore] = await getBalance(api, [alice.address]);137      balanceOpalBefore = await helper.balance.getSubstrate(alice.address);138139    });140141142    // Providing the relay currency to the unique sender account143    await usingPlaygrounds.atUrl(relayUrl, async (helper) => {144      const api = helper.getApi();145146      const destination = {147        V1: {148          parents: 0,149          interior: {X1: {150            Parachain: UNIQUE_CHAIN,151          },152          },153        }};154155      const beneficiary = {156        V1: {157          parents: 0,158          interior: {X1: {159            AccountId32: {160              network: 'Any',161              id: alice.addressRaw,162            },163          }},164        },165      };166167      const assets = {168        V1: [169          {170            id: {171              Concrete: {172                parents: 0,173                interior: 'Here',174              },175            },176            fun: {177              Fungible: 50_000_000_000_000_000n,178            },179          },180        ],181      };182183      const feeAssetItem = 0;184185      const weightLimit = {186        Limited: 5_000_000_000,187      };188189      const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);190      const events = await executeTransaction(api, alice, tx);191      const result = getGenericResult(events);192      expect(result.success).to.be.true;193    });194  195  });196197  itSub('Should connect and send USDT from Westmint to Opal', async ({helper}) => {198    await usingPlaygrounds.atUrl(statemineUrl, async (helper) => {199      const api = helper.getApi();200201      const dest = {202        V1: {203          parents: 1,204          interior: {X1: {205            Parachain: UNIQUE_CHAIN,206          },207          },208        }};209210      const beneficiary = {211        V1: {212          parents: 0,213          interior: {X1: {214            AccountId32: {215              network: 'Any',216              id: alice.addressRaw,217            },218          }},219        },220      };221222      const assets = {223        V1: [224          {225            id: {226              Concrete: {227                parents: 0,228                interior: {229                  X2: [230                    {231                      PalletInstance: STATEMINE_PALLET_INSTANCE,232                    },233                    {234                      GeneralIndex: ASSET_ID,235                    }, 236                  ]},237              },238            },239            fun: {240              Fungible: TRANSFER_AMOUNT,241            },242          },243        ],244      };245246      const feeAssetItem = 0;247248      const weightLimit = {249        Limited: 5000000000,250      };251252      [balanceStmnBefore] = await getBalance(api, [alice.address]);253254      const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(dest, beneficiary, assets, feeAssetItem, weightLimit);255      const events = await executeTransaction(api, alice, tx);256      const result = getGenericResult(events);257      expect(result.success).to.be.true;258259      [balanceStmnAfter] = await getBalance(api, [alice.address]);260261      // common good parachain take commission in it native token262      console.log(263        'Opal to Westmint transaction fees on Westmint: %s WND',264        bigIntToDecimals(balanceStmnBefore - balanceStmnAfter, WESTMINT_DECIMALS),265      );266      expect(balanceStmnBefore > balanceStmnAfter).to.be.true;267268    });269270271    // ensure that asset has been delivered272    // await waitNewBlocks(api, 3);273    await helper.wait.newBlocks(3);274275    // expext collection id will be with id 1276    // const free = (await api.query.fungible.balance(1, normalizeAccountId(alice.address))).toBigInt();277    const free = await helper.ft.getBalance(1, {Substrate: alice.address});278279    // [balanceOpalAfter] = await getBalance(api, [alice.address]);280    balanceOpalAfter = await helper.balance.getSubstrate(alice.address);281282    // commission has not paid in USDT token283    expect(free == TRANSFER_AMOUNT).to.be.true;284    console.log(285      'Opal to Westmint transaction fees on Opal: %s USDT',286      bigIntToDecimals(TRANSFER_AMOUNT - free),287    );288    // ... and parachain native token289    expect(balanceOpalAfter == balanceOpalBefore).to.be.true;290    console.log(291      'Opal to Westmint transaction fees on Opal: %s WND',292      bigIntToDecimals(balanceOpalAfter - balanceOpalBefore, WESTMINT_DECIMALS),293    );    294  });295296  itSub('Should connect and send USDT from Unique to Statemine back', async ({helper}) => {297    const api = helper.getApi();298299    const destination = {300      V1: {301        parents: 1,302        interior: {X2: [303          {304            Parachain: STATEMINE_CHAIN,305          },306          {307            AccountId32: {308              network: 'Any',309              id: alice.addressRaw,310            },311          },312        ]},313      },314    };315316    const currencies: [any, bigint][] = [317      [318        {319          ForeignAssetId: 0,320        },321        //10_000_000_000_000_000n,322        TRANSFER_AMOUNT,323      ], 324      [325        {326          NativeAssetId: 'Parent',327        },328        400_000_000_000_000n,329      ],330    ];331332    const feeItem = 1;333    const destWeight = 500000000000;334335    const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight);336    const events = await executeTransaction(api, alice, tx);337    const result = getGenericResult(events);338    expect(result.success).to.be.true;339    340    // the commission has been paid in parachain native token341    [balanceOpalFinal] = await getBalance(api, [alice.address]);342    expect(balanceOpalAfter > balanceOpalFinal).to.be.true;343344    await usingPlaygrounds.atUrl(statemineUrl, async (helper) => {345      // await waitNewBlocks(api, 3);346      await helper.wait.newBlocks(3);347348      const api = helper.getApi();349      350      // The USDT token never paid fees. Its amount not changed from begin value.351      // Also check that xcm transfer has been succeeded 352      const free = ((await api.query.assets.account(100, alice.address)).toHuman()) as any;353      expect(BigInt(free.balance.replace(/,/g, '')) == ASSET_AMOUNT).to.be.true;354    });355  });356357  itSub('Should connect and send Relay token to Unique', async ({helper}) => {358    const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;359360    // [balanceBobBefore] = await getBalance(api, [bob.address]);361    // balanceBobRelayTokenBefore = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free);362    balanceBobBefore = await helper.balance.getSubstrate(bob.address);363364    // TODO365    balanceBobRelayTokenBefore = BigInt(((await helper.getApi().query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free);366367    // Providing the relay currency to the unique sender account368    await usingPlaygrounds.atUrl(relayUrl, async (helper) => {369      const api = helper.getApi();370371      const destination = {372        V1: {373          parents: 0,374          interior: {X1: {375            Parachain: UNIQUE_CHAIN,376          },377          },378        }};379380      const beneficiary = {381        V1: {382          parents: 0,383          interior: {X1: {384            AccountId32: {385              network: 'Any',386              id: bob.addressRaw,387            },388          }},389        },390      };391392      const assets = {393        V1: [394          {395            id: {396              Concrete: {397                parents: 0,398                interior: 'Here',399              },400            },401            fun: {402              Fungible: TRANSFER_AMOUNT_RELAY,403            },404          },405        ],406      };407408      const feeAssetItem = 0;409410      const weightLimit = {411        Limited: 5_000_000_000,412      };413414      const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit);415      const events = await executeTransaction(api, bob, tx);416      const result = getGenericResult(events);417      expect(result.success).to.be.true;418    });419  420421    // await waitNewBlocks(api, 3);422    await helper.wait.newBlocks(3);423424    // [balanceBobAfter] = await getBalance(api, [bob.address]);425    // balanceBobRelayTokenAfter = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free);426    balanceBobAfter = await helper.balance.getSubstrate(bob.address);427    428    // TODO429    balanceBobRelayTokenAfter = BigInt(((await helper.getApi().query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free);430431    const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; 432    console.log(433      'Relay (Westend) to Opal transaction fees: %s OPL',434      bigIntToDecimals(balanceBobAfter - balanceBobBefore),435    );436    console.log(437      'Relay (Westend) to Opal transaction fees: %s WND',438      bigIntToDecimals(wndFee, WESTMINT_DECIMALS),439    );440    expect(balanceBobBefore == balanceBobAfter).to.be.true;441    expect(balanceBobRelayTokenBefore < balanceBobRelayTokenAfter).to.be.true;442  });443444  itSub('Should connect and send Relay token back', async ({helper}) => {445    const destination = {446      V1: {447        parents: 1,448        interior: {X2: [449          {450            Parachain: STATEMINE_CHAIN,451          },452          {453            AccountId32: {454              network: 'Any',455              id: bob.addressRaw,456            },457          },458        ]},459      },460    };461462    const currencies: any = [463      [464        {465          NativeAssetId: 'Parent',466        },467        50_000_000_000_000_000n,468      ],469    ];470471    const feeItem = 0;472    const destWeight = 500000000000;473474    // TODO475    const api = helper.getApi();476    const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight);477    const events = await executeTransaction(api, bob, tx);478    const result = getGenericResult(events);479    expect(result.success).to.be.true;480481    // [balanceBobFinal] = await getBalance(api, [bob.address]);482    balanceBobFinal = await helper.balance.getSubstrate(bob.address);483    console.log('Relay (Westend) to Opal transaction fees: %s OPL', balanceBobAfter - balanceBobFinal);484  });485486});
after · tests/src/xcm/xcmOpal.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {bigIntToDecimals, paraSiblingSovereignAccount} from './../deprecated-helpers/helpers';19import {itSub, expect, describeXcm, usingPlaygrounds, usingWestmintPlaygrounds, usingRelayPlaygrounds} from '../util/playgrounds';2021const STATEMINE_CHAIN = 1000;22const UNIQUE_CHAIN = 2095;2324const RELAY_PORT = '9844';25const STATEMINE_PORT = '9948';2627const relayUrl = 'ws://127.0.0.1:' + RELAY_PORT;28const statemineUrl = 'ws://127.0.0.1:' + STATEMINE_PORT;2930const STATEMINE_PALLET_INSTANCE = 50;31const ASSET_ID = 100;32const ASSET_METADATA_DECIMALS = 18;33const ASSET_METADATA_NAME = 'USDT';34const ASSET_METADATA_DESCRIPTION = 'USDT';35const ASSET_METADATA_MINIMAL_BALANCE = 1n;3637const WESTMINT_DECIMALS = 12;3839const TRANSFER_AMOUNT = 1_000_000_000_000_000_000n;4041// 10,000.00 (ten thousands) USDT42const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; 4344describeXcm('[XCM] Integration test: Exchanging USDT with Westmint', () => {45  let alice: IKeyringPair;46  let bob: IKeyringPair;47  48  let balanceStmnBefore: bigint;49  let balanceStmnAfter: bigint;5051  let balanceOpalBefore: bigint;52  let balanceOpalAfter: bigint;53  let balanceOpalFinal: bigint;5455  let balanceBobBefore: bigint;56  let balanceBobAfter: bigint;57  let balanceBobFinal: bigint;5859  let balanceBobRelayTokenBefore: bigint;60  let balanceBobRelayTokenAfter: bigint;616263  before(async () => {64    await usingPlaygrounds(async (_helper, privateKey) => {65      alice = privateKey('//Alice');66      bob = privateKey('//Bob'); // funds donor67    });6869    await usingWestmintPlaygrounds(statemineUrl, async (helper) => {70      // 350.00 (three hundred fifty) DOT71      const fundingAmount = 3_500_000_000_000n; 7273      await helper.assets.create(alice, ASSET_ID, alice.address, ASSET_METADATA_MINIMAL_BALANCE);74      await helper.assets.setMetadata(alice, ASSET_ID, ASSET_METADATA_NAME, ASSET_METADATA_DESCRIPTION, ASSET_METADATA_DECIMALS);75      await helper.assets.mint(alice, ASSET_ID, alice.address, ASSET_AMOUNT);7677      // funding parachain sovereing account (Parachain: 2095)78      const parachainSovereingAccount = await paraSiblingSovereignAccount(UNIQUE_CHAIN);79      await helper.balance.transferToSubstrate(bob, parachainSovereingAccount, fundingAmount);80    });818283    await usingPlaygrounds(async (helper) => {84      const location = {85        V1: {86          parents: 1,87          interior: {X3: [88            {89              Parachain: STATEMINE_CHAIN,90            },91            {92              PalletInstance: STATEMINE_PALLET_INSTANCE,93            },94            {95              GeneralIndex: ASSET_ID,96            },97          ]},98        },99      };100101      const metadata =102      {103        name: ASSET_ID,104        symbol: ASSET_METADATA_NAME,105        decimals: ASSET_METADATA_DECIMALS,106        minimalBalance: ASSET_METADATA_MINIMAL_BALANCE,107      };108      await helper.getSudo().foreignAssets.register(alice, alice.address, location, metadata);109      balanceOpalBefore = await helper.balance.getSubstrate(alice.address);110    });111112113    // Providing the relay currency to the unique sender account114    await usingRelayPlaygrounds(relayUrl, async (helper) => {115      const destination = {116        V1: {117          parents: 0,118          interior: {X1: {119            Parachain: UNIQUE_CHAIN,120          },121          },122        }};123124      const beneficiary = {125        V1: {126          parents: 0,127          interior: {X1: {128            AccountId32: {129              network: 'Any',130              id: alice.addressRaw,131            },132          }},133        },134      };135136      const assets = {137        V1: [138          {139            id: {140              Concrete: {141                parents: 0,142                interior: 'Here',143              },144            },145            fun: {146              Fungible: 50_000_000_000_000_000n,147            },148          },149        ],150      };151152      const feeAssetItem = 0;153      const weightLimit = 5_000_000_000;154155      await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, weightLimit);156    });157  158  });159160  itSub('Should connect and send USDT from Westmint to Opal', async ({helper}) => {161    await usingWestmintPlaygrounds(statemineUrl, async (helper) => {162      const dest = {163        V1: {164          parents: 1,165          interior: {X1: {166            Parachain: UNIQUE_CHAIN,167          },168          },169        }};170171      const beneficiary = {172        V1: {173          parents: 0,174          interior: {X1: {175            AccountId32: {176              network: 'Any',177              id: alice.addressRaw,178            },179          }},180        },181      };182183      const assets = {184        V1: [185          {186            id: {187              Concrete: {188                parents: 0,189                interior: {190                  X2: [191                    {192                      PalletInstance: STATEMINE_PALLET_INSTANCE,193                    },194                    {195                      GeneralIndex: ASSET_ID,196                    }, 197                  ]},198              },199            },200            fun: {201              Fungible: TRANSFER_AMOUNT,202            },203          },204        ],205      };206207      const feeAssetItem = 0;208      const weightLimit = 5000000000;209210      balanceStmnBefore = await helper.balance.getSubstrate(alice.address);211      await helper.xcm.limitedReserveTransferAssets(alice, dest, beneficiary, assets, feeAssetItem, weightLimit);212213      balanceStmnAfter = await helper.balance.getSubstrate(alice.address);214215      // common good parachain take commission in it native token216      console.log(217        'Opal to Westmint transaction fees on Westmint: %s WND',218        bigIntToDecimals(balanceStmnBefore - balanceStmnAfter, WESTMINT_DECIMALS),219      );220      expect(balanceStmnBefore > balanceStmnAfter).to.be.true;221222    });223224225    // ensure that asset has been delivered226    await helper.wait.newBlocks(3);227228    // expext collection id will be with id 1229    const free = await helper.ft.getBalance(1, {Substrate: alice.address});230231    balanceOpalAfter = await helper.balance.getSubstrate(alice.address);232233    // commission has not paid in USDT token234    expect(free == TRANSFER_AMOUNT).to.be.true;235    console.log(236      'Opal to Westmint transaction fees on Opal: %s USDT',237      bigIntToDecimals(TRANSFER_AMOUNT - free),238    );239    // ... and parachain native token240    expect(balanceOpalAfter == balanceOpalBefore).to.be.true;241    console.log(242      'Opal to Westmint transaction fees on Opal: %s WND',243      bigIntToDecimals(balanceOpalAfter - balanceOpalBefore, WESTMINT_DECIMALS),244    );    245  });246247  itSub('Should connect and send USDT from Unique to Statemine back', async ({helper}) => {248    const destination = {249      V1: {250        parents: 1,251        interior: {X2: [252          {253            Parachain: STATEMINE_CHAIN,254          },255          {256            AccountId32: {257              network: 'Any',258              id: alice.addressRaw,259            },260          },261        ]},262      },263    };264265    const currencies: [any, bigint][] = [266      [267        {268          ForeignAssetId: 0,269        },270        //10_000_000_000_000_000n,271        TRANSFER_AMOUNT,272      ], 273      [274        {275          NativeAssetId: 'Parent',276        },277        400_000_000_000_000n,278      ],279    ];280281    const feeItem = 1;282    const destWeight = 500000000000;283284    await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, destWeight);285    286    // the commission has been paid in parachain native token287    balanceOpalFinal = await helper.balance.getSubstrate(alice.address);288    expect(balanceOpalAfter > balanceOpalFinal).to.be.true;289290    await usingWestmintPlaygrounds(statemineUrl, async (helper) => {291      await helper.wait.newBlocks(3);292      293      // The USDT token never paid fees. Its amount not changed from begin value.294      // Also check that xcm transfer has been succeeded 295      expect((await helper.assets.account(ASSET_ID, alice.address))! == ASSET_AMOUNT).to.be.true;296    });297  });298299  itSub('Should connect and send Relay token to Unique', async ({helper}) => {300    const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;301302    balanceBobBefore = await helper.balance.getSubstrate(bob.address);303    balanceBobRelayTokenBefore = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});304305    // Providing the relay currency to the unique sender account306    await usingRelayPlaygrounds(relayUrl, async (helper) => {307      const destination = {308        V1: {309          parents: 0,310          interior: {X1: {311            Parachain: UNIQUE_CHAIN,312          },313          },314        }};315316      const beneficiary = {317        V1: {318          parents: 0,319          interior: {X1: {320            AccountId32: {321              network: 'Any',322              id: bob.addressRaw,323            },324          }},325        },326      };327328      const assets = {329        V1: [330          {331            id: {332              Concrete: {333                parents: 0,334                interior: 'Here',335              },336            },337            fun: {338              Fungible: TRANSFER_AMOUNT_RELAY,339            },340          },341        ],342      };343344      const feeAssetItem = 0;345      const weightLimit = 5_000_000_000;346347      await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, weightLimit);348    });349  350    await helper.wait.newBlocks(3);351352    balanceBobAfter = await helper.balance.getSubstrate(bob.address);  353    balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});354355    const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; 356    console.log(357      'Relay (Westend) to Opal transaction fees: %s OPL',358      bigIntToDecimals(balanceBobAfter - balanceBobBefore),359    );360    console.log(361      'Relay (Westend) to Opal transaction fees: %s WND',362      bigIntToDecimals(wndFee, WESTMINT_DECIMALS),363    );364    expect(balanceBobBefore == balanceBobAfter).to.be.true;365    expect(balanceBobRelayTokenBefore < balanceBobRelayTokenAfter).to.be.true;366  });367368  itSub('Should connect and send Relay token back', async ({helper}) => {369    const destination = {370      V1: {371        parents: 1,372        interior: {X2: [373          {374            Parachain: STATEMINE_CHAIN,375          },376          {377            AccountId32: {378              network: 'Any',379              id: bob.addressRaw,380            },381          },382        ]},383      },384    };385386    const currencies: any = [387      [388        {389          NativeAssetId: 'Parent',390        },391        50_000_000_000_000_000n,392      ],393    ];394395    const feeItem = 0;396    const destWeight = 500000000000;397398    await helper.xTokens.transferMulticurrencies(bob, currencies, feeItem, destination, destWeight);399400    balanceBobFinal = await helper.balance.getSubstrate(bob.address);401    console.log('Relay (Westend) to Opal transaction fees: %s OPL', balanceBobAfter - balanceBobFinal);402  });403});