Skip to content

Commit

Permalink
Merge pull request #90 from galacticcouncil/fix/hub-keys
Browse files Browse the repository at this point in the history
Fix hub foreign asset keys
  • Loading branch information
nohaapav authored Nov 19, 2024
2 parents 7b2d098 + 84ef243 commit f30db28
Show file tree
Hide file tree
Showing 23 changed files with 1,222 additions and 285 deletions.
5 changes: 5 additions & 0 deletions .changeset/violet-shirts-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@galacticcouncil/xcm-cfg': patch
---

Fix assethub foreign balance location (v3 -> v4)
276 changes: 159 additions & 117 deletions integration-tests/xcm-test/src/__snapshots__/call.spec.ts.snap

Large diffs are not rendered by default.

505 changes: 505 additions & 0 deletions integration-tests/xcm-test/src/__snapshots__/e2e.spec.ts.snap

Large diffs are not rendered by default.

118 changes: 91 additions & 27 deletions integration-tests/xcm-test/src/call.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,8 @@ const jestConsole = console;
const { configService, init } = setup;
const { runXcm } = xcm;

describe('Wallet with XCM config', () => {
jest.setTimeout(3 * 60 * 1000); // Execution time <= 3 min

let wallet: Wallet;

const blacklist = ['acala-evm'];
const getPolkadotChains = () => {
const blacklist: string[] = ['acala-evm'];
const chains = Array.from(configService.chains.values())
.filter(
(c) =>
Expand All @@ -25,6 +21,32 @@ describe('Wallet with XCM config', () => {
)
.filter((c) => !blacklist.includes(c.key));

return {
blacklist,
chains,
};
};

const getKusamaChains = () => {
const blacklist: string[] = ['basilisk'];
const chains = Array.from(configService.chains.values())
.filter((c) => c.ecosystem === ChainEcosystem.Kusama)
.filter((c) => !blacklist.includes(c.key));

return {
blacklist,
chains,
};
};

describe('Wallet with XCM config', () => {
jest.setTimeout(3 * 60 * 1000); // Execution time <= 3 min

let wallet: Wallet;

const polkadot = getPolkadotChains();
const kusama = getKusamaChains();

beforeAll(async () => {
global.console = console;
console.log('Starting suite 👷 ...\n');
Expand All @@ -40,27 +62,69 @@ describe('Wallet with XCM config', () => {
expect(wallet).toBeDefined();
});

describe.each(chains)('should return valid calldata for', (c) => {
const config = configService.getChainRoutes(c);
const { chain, routes } = config;

for (const route of Array.from(routes.values())) {
const info = getRouteInfo(chain, route);

runXcm(
`${info} transfer`,
async () => {
return {
chain: chain,
route: route,
};
},
async () => {
return {
wallet: wallet,
};
describe.each(polkadot.chains)(
'should return valid Polkadot calldata for',
(c) => {
const config = configService.getChainRoutes(c);
const { chain, routes } = config;

for (const route of Array.from(routes.values())) {
const { blacklist } = polkadot;
const { destination } = route;

if (blacklist.includes(destination.chain.key)) {
continue;
}
);

const info = getRouteInfo(chain, route);
runXcm(
`${info} transfer`,
async () => {
return {
chain: chain,
route: route,
};
},
async () => {
return {
wallet: wallet,
};
}
);
}
}
});
);

describe.each(kusama.chains)(
'should return valid Kusama calldata for',
(c) => {
const config = configService.getChainRoutes(c);
const { chain, routes } = config;

for (const route of Array.from(routes.values())) {
const { blacklist } = kusama;
const { destination } = route;

if (blacklist.includes(destination.chain.key)) {
continue;
}

const info = getRouteInfo(chain, route);
runXcm(
`${info} transfer`,
async () => {
return {
chain: chain,
route: route,
};
},
async () => {
return {
wallet: wallet,
};
}
);
}
}
);
});
97 changes: 57 additions & 40 deletions integration-tests/xcm-test/src/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,94 @@ import console from 'console';

import { setup, network, xcm, SetupCtx } from './e2e';
import { getRouteInfo } from './utils';
import { write, loadExisting } from './file';

const jestConsole = console;
const DB = 'metadata.db.json';

const { configService, initWithCtx } = setup;
const { createNetworks } = network;
const { runXcm } = xcm;

const getPolkadotChains = () => {
const bridge: string[] = ['ethereum'];
const blacklist: string[] = bridge.concat(['acala-evm', 'nodle']);
const chains: Parachain[] = Array.from(configService.chains.values())
.filter((c) => c instanceof Parachain)
.filter((c) => c.ecosystem === ChainEcosystem.Polkadot)
.filter((c) => !blacklist.includes(c.key));

return {
blacklist,
bridge,
chains,
};
};

describe('Wallet with XCM config', () => {
jest.setTimeout(3 * 60 * 1000); // Execution time <= 3 min

let wallet: Wallet;
let networks: SetupCtx[] = [];

const blacklist = ['acala-evm', 'acala', 'nodle'];
const bridge = ['ethereum'];
const chains = Array.from(configService.chains.values())
.filter((c) => c instanceof Parachain)
.filter((c) => c.ecosystem === ChainEcosystem.Polkadot)
.filter((c) => !blacklist.includes(c.key));
const reportCtx = loadExisting(DB);
const polkadot = getPolkadotChains();

beforeAll(async () => {
global.console = console;
networks = await createNetworks(chains);
networks = await createNetworks(polkadot.chains);
const ctx = networks.find((n) => n.config.key === 'hydration')!;
wallet = await initWithCtx(ctx);
});

afterAll(async () => {
global.console = jestConsole;
await Promise.all(networks.map((network) => network.teardown()));
await SubstrateApis.getInstance().release();
await Promise.all(networks.map((network) => network.teardown()));
write(reportCtx, DB);
});

it('is defined', () => {
expect(configService).toBeDefined();
});

describe.each(chains)('should result in valid transfer for', (c) => {
const config = configService.getChainRoutes(c);
const { chain, routes } = config;
describe.each(polkadot.chains)(
'should result in valid Polkadot transfer for',
(c) => {
const config = configService.getChainRoutes(c);
const { chain, routes } = config;

for (const route of Array.from(routes.values())) {
const skip = bridge
.concat(blacklist)
.includes(route.destination.chain.key);
if (skip) {
continue;
}
for (const route of Array.from(routes.values())) {
const { blacklist } = polkadot;
const { destination } = route;

const info = getRouteInfo(chain, route);
runXcm(
`${info} transfer`,
async () => {
return {
chain: chain,
route: route,
};
},
async () => {
return {
networks: networks,
wallet: wallet,
};
},
{
skip:
chain.key != 'hydration' ||
route.destination.chain.key != 'zeitgeist',
//route.source.asset.key != 'wbtc_mwh',
if (blacklist.includes(destination.chain.key)) {
continue;
}
);

const isContractTransfer = !!route.contract;

const info = getRouteInfo(chain, route);
runXcm(
`${info} transfer`,
async () => {
return {
chain: chain,
route: route,
};
},
async () => {
return {
report: reportCtx,
networks: networks,
wallet: wallet,
};
},
{
skip: isContractTransfer,
}
);
}
}
});
);
});
13 changes: 13 additions & 0 deletions integration-tests/xcm-test/src/e2e/amount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Asset, AssetAmount } from '@galacticcouncil/xcm-core';

export const getAmount = async (
amount: number,
asset: Asset,
assetDecimals: number
) => {
const assetAmount = amount * 10 ** assetDecimals;
return AssetAmount.fromAsset(asset, {
decimals: assetDecimals,
amount: BigInt(assetAmount),
});
};
70 changes: 70 additions & 0 deletions integration-tests/xcm-test/src/e2e/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type {
DispatchError,
EventRecord,
} from '@polkadot/types/interfaces/system';
import type { AnyJson } from '@polkadot/types-codec/types';
import { ApiPromise } from '@polkadot/api';

import { findNestedKey } from '../utils';

export function checkIfFailed(api: ApiPromise, events: EventRecord[]): boolean {
return events.some(({ event: { method, section, data } }) => {
const eventData = data.toHuman();
if (section === 'system' && method === 'ExtrinsicFailed') {
logEvent(section, method, eventData);
logError(api, data);
return true;
}
return false;
});
}

export function checkIfSent(events: EventRecord[]): boolean {
return events.some(({ event: { method, section, data } }) => {
const eventData = data.toHuman();
switch (section) {
case 'xcmpQueue':
logEvent(section, method, eventData);
return method === 'XcmpMessageSent';
default:
return false;
}
});
}

export function checkIfProcessed(events: EventRecord[]): boolean {
return events.some(({ event: { method, section, data } }) => {
const eventData = data.toHuman();
switch (section) {
case 'messageQueue':
logEvent(section, method, eventData);
return method === 'Processed' && checkProcessedStatus(eventData);
case 'xcmpQueue':
logEvent(section, method, eventData);
return method === 'Success';
case 'dmpQueue':
logEvent(section, method, eventData);
return method === 'ExecutedDownward';
default:
return false;
}
});
}

function checkProcessedStatus(data: AnyJson): boolean {
const dataEntry = findNestedKey(data, 'success');
return dataEntry['success'] === true;
}

function logEvent(section: string, method: string, data: AnyJson) {
console.log('🥢 STATUS: ' + section + '.' + method, data);
}

function logError(api: ApiPromise, data: any) {
const { dispatchError } = data;
const error = dispatchError as DispatchError;
const decoded = api.registry.findMetaError(error.asModule);
console.error(
`🥢 ${decoded.section}.${decoded.method}: ${decoded.docs.join(' ')}`
);
}
1 change: 1 addition & 0 deletions integration-tests/xcm-test/src/e2e/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as moonbeam from './moonbeam';
Loading

0 comments on commit f30db28

Please sign in to comment.