git.delta.rocks / unique-network / refs/commits / 683a1283827b

difftreelog

test added CI for the Polkadex network

PraetorP2023-09-11parent: #2fcc0ad.patch.diff
in: master

7 files changed

addedtests/.mocha.envdiffbeforeafterboth

no changes

modifiedtests/.vscode/settings.jsondiffbeforeafterboth
1{1{
2 "mocha.enabled": true,2 "mochaExplorer.env": {
3 "RUN_GOV_TESTS": "1",
4 "RUN_XCM_TESTS": "1"
5 },
3 "mochaExplorer.files": "**/*.test.ts",6 "mochaExplorer.files": "src/**/*.test.ts",
7 "mochaExplorer.envPath": ".mocha.env",
4 "mochaExplorer.require": "ts-node/register",8 "mochaExplorer.require": "ts-node/register",
5 "eslint.format.enable": true,9 "eslint.format.enable": true,
6 "[javascript]": {10 "[javascript]": {
modifiedtests/src/config.tsdiffbeforeafterboth
28 westmintUrl: process.env.RELAY_WESTMINT_URL || 'ws://127.0.0.1:9948',28 westmintUrl: process.env.RELAY_WESTMINT_URL || 'ws://127.0.0.1:9948',
29 statemineUrl: process.env.RELAY_STATEMINE_URL || 'ws://127.0.0.1:9948',29 statemineUrl: process.env.RELAY_STATEMINE_URL || 'ws://127.0.0.1:9948',
30 statemintUrl: process.env.RELAY_STATEMINT_URL || 'ws://127.0.0.1:9948',30 statemintUrl: process.env.RELAY_STATEMINT_URL || 'ws://127.0.0.1:9948',
31 polkadexUrl: process.env.RELAY_POLKADEX_URL || 'ws://127.0.0.1:9950',
31};32};
3233
33export default config;34export default config;
modifiedtests/src/util/index.tsdiffbeforeafterboth
11import config from '../config';11import config from '../config';
12import {ChainHelperBase} from './playgrounds/unique';12import {ChainHelperBase} from './playgrounds/unique';
13import {ILogger} from './playgrounds/types';13import {ILogger} from './playgrounds/types';
14import {DevUniqueHelper, SilentLogger, SilentConsole, DevMoonbeamHelper, DevMoonriverHelper, DevAcalaHelper, DevKaruraHelper, DevRelayHelper, DevWestmintHelper, DevStatemineHelper, DevStatemintHelper, DevAstarHelper, DevShidenHelper} from './playgrounds/unique.dev';14import {DevUniqueHelper, SilentLogger, SilentConsole, DevMoonbeamHelper, DevMoonriverHelper, DevAcalaHelper, DevKaruraHelper, DevRelayHelper, DevWestmintHelper, DevStatemineHelper, DevStatemintHelper, DevAstarHelper, DevShidenHelper, DevPolkadexHelper} from './playgrounds/unique.dev';
15import {dirname} from 'path';15import {dirname} from 'path';
16import {fileURLToPath} from 'url';16import {fileURLToPath} from 'url';
1717
8989
90export const usingShidenPlaygrounds = (url: string, code: (helper: DevShidenHelper, privateKey: (seed: string) => Promise<IKeyringPair>) => Promise<void>) => usingPlaygroundsGeneral<DevShidenHelper>(DevShidenHelper, url, code);90export const usingShidenPlaygrounds = (url: string, code: (helper: DevShidenHelper, privateKey: (seed: string) => Promise<IKeyringPair>) => Promise<void>) => usingPlaygroundsGeneral<DevShidenHelper>(DevShidenHelper, url, code);
91
92export const usingPolkadexPlaygrounds = (url: string, code: (helper: DevPolkadexHelper, privateKey: (seed: string) => Promise<IKeyringPair>) => Promise<void>) => usingPlaygroundsGeneral<DevPolkadexHelper>(DevPolkadexHelper, url, code);
9193
92export const MINIMUM_DONOR_FUND = 4_000_000n;94export const MINIMUM_DONOR_FUND = 4_000_000n;
93export const DONOR_FUNDING = 4_000_000n;95export const DONOR_FUNDING = 4_000_000n;
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
33
4import {stringToU8a} from '@polkadot/util';4import {stringToU8a} from '@polkadot/util';
5import {blake2AsHex, encodeAddress, mnemonicGenerate} from '@polkadot/util-crypto';5import {blake2AsHex, encodeAddress, mnemonicGenerate} from '@polkadot/util-crypto';
6import {UniqueHelper, MoonbeamHelper, ChainHelperBase, AcalaHelper, RelayHelper, WestmintHelper, AstarHelper} from './unique';6import {UniqueHelper, MoonbeamHelper, ChainHelperBase, AcalaHelper, RelayHelper, WestmintHelper, AstarHelper, PolkadexHelper} from './unique';
7import {ApiPromise, Keyring, WsProvider} from '@polkadot/api';7import {ApiPromise, Keyring, WsProvider} from '@polkadot/api';
8import * as defs from '../../interfaces/definitions';8import * as defs from '../../interfaces/definitions';
9import {IKeyringPair} from '@polkadot/types/types';9import {IKeyringPair} from '@polkadot/types/types';
249 messageHash: eventJsonData(data, 0),249 messageHash: eventJsonData(data, 0),
250 }));250 }));
251
252 static Success = this.Method('Success', data => ({
253 messageHash: eventJsonData(data, 0),
254 }));
251255
252 static Fail = this.Method('Fail', data => ({256 static Fail = this.Method('Fail', data => ({
253 messageHash: eventJsonData(data, 0),257 messageHash: eventJsonData(data, 0),
406 }410 }
407}411}
412
413export class DevPolkadexHelper extends PolkadexHelper {
414 wait: WaitGroup;
415 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {
416 options.helperBase = options.helperBase ?? PolkadexHelper;
417
418 super(logger, options);
419 this.wait = new WaitGroup(this);
420 }
421}
408422
409export class DevKaruraHelper extends DevAcalaHelper {}423export class DevKaruraHelper extends DevAcalaHelper {}
410424
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
3694 }3694 }
3695}3695}
3696
3697class PolkadexXcmHelperGroup<T extends ChainHelperBase> extends HelperGroup<T> {
3698 async whitelistToken(signer: TSigner, assetId: any) {
3699 await this.helper.executeExtrinsic(signer, 'api.tx.xcmHelper.whitelistToken', [assetId], true);
3700 }
3701}
36963702
3697class TokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {3703class TokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {
3698 async accounts(address: string, currencyId: any) {3704 async accounts(address: string, currencyId: any) {
3977 }3983 }
3978}3984}
3985
3986export class PolkadexHelper extends XcmChainHelper {
3987 assets: AssetsGroup<PolkadexHelper>;
3988 balance: SubstrateBalanceGroup<PolkadexHelper>;
3989 xTokens: XTokensGroup<PolkadexHelper>;
3990 xcm: XcmGroup<PolkadexHelper>;
3991 xcmHelper: PolkadexXcmHelperGroup<PolkadexHelper>;
3992
3993 constructor(logger?: ILogger, options: { [key: string]: any } = {}) {
3994 super(logger, options.helperBase ?? PolkadexHelper);
3995
3996 this.assets = new AssetsGroup(this);
3997 this.balance = new SubstrateBalanceGroup(this);
3998 this.xTokens = new XTokensGroup(this);
3999 this.xcm = new XcmGroup(this, 'polkadotXcm');
4000 this.xcmHelper = new PolkadexXcmHelperGroup(this);
4001 }
4002
4003 getSudo<T extends PolkadexHelper>() {
4004 // eslint-disable-next-line @typescript-eslint/naming-convention
4005 const SudoHelperType = SudoHelper(this.helperBase);
4006 return this.clone(SudoHelperType) as T;
4007 }
4008}
39794009
3980// eslint-disable-next-line @typescript-eslint/naming-convention4010// eslint-disable-next-line @typescript-eslint/naming-convention
3981function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {4011function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {
modifiedtests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import config from '../config';18import config from '../config';
19import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds, usingAstarPlaygrounds} from '../util';19import {itSub, expect, describeXCM, usingPlaygrounds, usingAcalaPlaygrounds, usingRelayPlaygrounds, usingMoonbeamPlaygrounds, usingStatemintPlaygrounds, usingAstarPlaygrounds, usingPolkadexPlaygrounds} from '../util';
20import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';20import {DevUniqueHelper, Event} from '../util/playgrounds/unique.dev';
21import {nToBigInt} from '@polkadot/util';
2122
22const UNIQUE_CHAIN = +(process.env.RELAY_UNIQUE_ID || 2037);23const UNIQUE_CHAIN = +(process.env.RELAY_UNIQUE_ID || 2037);
23const STATEMINT_CHAIN = +(process.env.RELAY_STATEMINT_ID || 1000);24const STATEMINT_CHAIN = +(process.env.RELAY_STATEMINT_ID || 1000);
24const ACALA_CHAIN = +(process.env.RELAY_ACALA_ID || 2000);25const ACALA_CHAIN = +(process.env.RELAY_ACALA_ID || 2000);
25const MOONBEAM_CHAIN = +(process.env.RELAY_MOONBEAM_ID || 2004);26const MOONBEAM_CHAIN = +(process.env.RELAY_MOONBEAM_ID || 2004);
26const ASTAR_CHAIN = +(process.env.RELAY_ASTAR_ID || 2006);27const ASTAR_CHAIN = +(process.env.RELAY_ASTAR_ID || 2006);
28const POLKADEX_CHAIN = +(process.env.RELAY_POLKADEX_ID || 2040);
2729
28const STATEMINT_PALLET_INSTANCE = 50;30const STATEMINT_PALLET_INSTANCE = 50;
2931
32const acalaUrl = config.acalaUrl;34const acalaUrl = config.acalaUrl;
33const moonbeamUrl = config.moonbeamUrl;35const moonbeamUrl = config.moonbeamUrl;
34const astarUrl = config.astarUrl;36const astarUrl = config.astarUrl;
37const polkadexUrl = config.polkadexUrl;
3538
36const RELAY_DECIMALS = 12;39const RELAY_DECIMALS = 12;
37const STATEMINT_DECIMALS = 12;40const STATEMINT_DECIMALS = 12;
791 });794 });
792});795});
796
797describeXCM('[XCM] Integration test: Exchanging tokens with Polkadex', () => {
798 let alice: IKeyringPair;
799 let randomAccount: IKeyringPair;
800 let unqFees: bigint;
801 let balanceUniqueTokenInit: bigint;
802 let balanceUniqueTokenMiddle: bigint;
803 let balanceUniqueTokenFinal: bigint;
804 const maxWaitBlocks = 6;
805
806 const uniqueAssetId = {
807 Concrete: {
808 parents: 1,
809 interior: {
810 X1: {
811 Parachain: UNIQUE_CHAIN,
812 },
813 },
814 },
815 };
816
817 before(async () => {
818 await usingPlaygrounds(async (helper, privateKey) => {
819 alice = await privateKey('//Alice');
820 [randomAccount] = await helper.arrange.createAccounts([0n], alice);
821
822 // Set the default version to wrap the first message to other chains.
823 await helper.getSudo().xcm.setSafeXcmVersion(alice, SAFE_XCM_VERSION);
824 });
825
826 await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {
827 const isWhitelisted = ((await helper.callRpc('api.query.xcmHelper.whitelistedTokens', [])).toJSON() as [])
828 .map(nToBigInt).length != 0;
829
830 if(!isWhitelisted) {
831 await helper.getSudo().xcmHelper.whitelistToken(alice, uniqueAssetId);
832 }
833
834 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10000000000000n);
835 });
836
837 await usingPlaygrounds(async (helper) => {
838 await helper.balance.transferToSubstrate(alice, randomAccount.address, 10n * TRANSFER_AMOUNT);
839 balanceUniqueTokenInit = await helper.balance.getSubstrate(randomAccount.address);
840 });
841 });
842
843 itSub('Should connect and send UNQ to Polkadex', async ({helper}) => {
844
845 const destination = {
846 V2: {
847 parents: 1,
848 interior: {
849 X1: {
850 Parachain: POLKADEX_CHAIN,
851 },
852 },
853 },
854 };
855
856 const beneficiary = {
857 V2: {
858 parents: 0,
859 interior: {
860 X1: {
861 AccountId32: {
862 network: 'Any',
863 id: randomAccount.addressRaw,
864 },
865 },
866 },
867 },
868 };
869
870 const assets = {
871 V2: [
872 {
873 id: {
874 Concrete: {
875 parents: 0,
876 interior: 'Here',
877 },
878 },
879 fun: {
880 Fungible: TRANSFER_AMOUNT,
881 },
882 },
883 ],
884 };
885
886 const feeAssetItem = 0;
887
888 await helper.xcm.limitedReserveTransferAssets(randomAccount, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
889 const messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
890 balanceUniqueTokenMiddle = await helper.balance.getSubstrate(randomAccount.address);
891
892 unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT;
893 console.log('[Unique -> Polkadex] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(unqFees));
894 expect(unqFees > 0n, 'Negative fees UNQ, looks like nothing was transferred').to.be.true;
895
896 await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {
897 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => event.messageHash == messageSent.messageHash);
898 });
899 });
900
901
902 itSub('Should connect to Polkadex and send UNQ back', async ({helper}) => {
903
904 const uniqueMultilocation = {
905 V2: {
906 parents: 1,
907 interior: {
908 X1: {Parachain: UNIQUE_CHAIN},
909 },
910 },
911 };
912
913 const xcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(
914 randomAccount.addressRaw,
915 {
916 Concrete: {
917 parents: 0,
918 interior: 'Here',
919 },
920 },
921 TRANSFER_AMOUNT,
922 );
923
924 let xcmProgramSent: any;
925
926
927 await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {
928 await helper.getSudo().xcm.send(alice, uniqueMultilocation, xcmProgram);
929
930 xcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
931 });
932
933 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Success, event => event.messageHash == xcmProgramSent.messageHash);
934
935 balanceUniqueTokenFinal = await helper.balance.getSubstrate(randomAccount.address);
936
937 expect(balanceUniqueTokenFinal).to.be.equal(balanceUniqueTokenInit - unqFees);
938 });
939
940 itSub('Polkadex can send only up to its balance', async ({helper}) => {
941 const polkadexBalance = 10000n * (10n ** UNQ_DECIMALS);
942 const polkadexSovereignAccount = helper.address.paraSiblingSovereignAccount(POLKADEX_CHAIN);
943 await helper.getSudo().balance.setBalanceSubstrate(alice, polkadexSovereignAccount, polkadexBalance);
944 const moreThanPolkadexHas = 2n * polkadexBalance;
945
946 const targetAccount = helper.arrange.createEmptyAccount();
947
948 const uniqueMultilocation = {
949 V2: {
950 parents: 1,
951 interior: {
952 X1: {Parachain: UNIQUE_CHAIN},
953 },
954 },
955 };
956
957 const maliciousXcmProgram = helper.arrange.makeXcmProgramWithdrawDeposit(
958 targetAccount.addressRaw,
959 {
960 Concrete: {
961 parents: 0,
962 interior: 'Here',
963 },
964 },
965 moreThanPolkadexHas,
966 );
967
968 let maliciousXcmProgramSent: any;
969
970
971 await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {
972 await helper.getSudo().xcm.send(alice, uniqueMultilocation, maliciousXcmProgram);
973
974 maliciousXcmProgramSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
975 });
976
977 await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.Fail, event => event.messageHash == maliciousXcmProgramSent.messageHash);
978
979 const targetAccountBalance = await helper.balance.getSubstrate(targetAccount.address);
980 expect(targetAccountBalance).to.be.equal(0n);
981 });
982});
793983
794// These tests are relevant only when984// These tests are relevant only when
795// the the corresponding foreign assets are not registered985// the the corresponding foreign assets are not registered
931 await expectFailedToTransact(helper, messageSent);1121 await expectFailedToTransact(helper, messageSent);
932 });1122 });
1123
1124 itSub('Unique rejects PDX tokens from Polkadex', async ({helper}) => {
1125
1126 const maliciousXcmProgramFullId = helper.arrange.makeXcmProgramReserveAssetDeposited(
1127 helper.arrange.createEmptyAccount().addressRaw,
1128 {
1129 Concrete: {
1130 parents: 1,
1131 interior: {
1132 X1: {
1133 Parachain: POLKADEX_CHAIN,
1134 },
1135 },
1136 },
1137 },
1138 testAmount,
1139 );
1140
1141 await usingPolkadexPlaygrounds(polkadexUrl, async (helper) => {
1142 await helper.getSudo().xcm.send(alice, uniqueParachainMultilocation, maliciousXcmProgramFullId);
1143 messageSent = await helper.wait.expectEvent(maxWaitBlocks, Event.XcmpQueue.XcmpMessageSent);
1144 });
1145
1146 await expectFailedToTransact(helper, messageSent);
1147 });
933});1148});
9341149
935describeXCM('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => {1150describeXCM('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => {