Skip to content

Commit

Permalink
feat: refactored convert command logic to fix issues
Browse files Browse the repository at this point in the history
  • Loading branch information
l0r1s committed Apr 11, 2023
1 parent 4a15fb2 commit 3254cbf
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 110 deletions.
204 changes: 123 additions & 81 deletions javascript/packages/cli/src/actions/convert.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,159 @@
import type {
NodeConfig,
ParachainConfig,
PolkadotLaunchConfig,
} from "@zombienet/orchestrator";
import { decorators, getFilePathNameExt } from "@zombienet/utils";
import fs from "fs";
import type { PolkadotLaunchConfig as ZombienetConfig } from "@zombienet/orchestrator";
import { decorators } from "@zombienet/utils";
import fs from "fs/promises";
import path from "path";
import { PL_ConfigType, PL_NodesConfig } from "src/types";
import { PolkadotLaunch } from "src/types";
import { DEFAULT_BALANCE } from "../constants";

export async function convert(param: string) {
try {
const filePath = param;
type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

export async function convert(filePath: string) {
try {
if (!filePath) {
throw Error("Path of configuration file was not provided");
}

// Read through the JSON and write to stream sample
await convertInput(filePath);
const { baseName, config } = await readPolkadotLaunchConfigFile(filePath);
const convertedConfig = await convertConfig(config);
await persistConfig(convertedConfig, baseName);
} catch (err) {
console.log(
`\n ${decorators.red("Error: ")} \t ${decorators.bright(err)}\n`,
);
}
}

// Convert functions
// Read the input file
async function readInputFile(
ext: string,
fPath: string,
): Promise<PL_ConfigType> {
if (ext === "json" || ext === "js") {
return ext === "json"
? JSON.parse(fs.readFileSync(`${fPath}`, "utf8"))
: await import(path.resolve(fPath));
async function readPolkadotLaunchConfigFile(filePath: string): Promise<{
baseName: string;
config: PolkadotLaunch.LaunchConfig;
}> {
const extension = path.extname(filePath);
const baseName = path.basename(filePath, extension);
let config;

console.log(extension);
if (extension === ".json") {
config = JSON.parse(await fs.readFile(filePath, "utf-8"));
} else if (extension === ".js") {
config = (await import(path.resolve(filePath))).config;
} else {
throw new Error("No valid extension was found.");
}

throw Error("No valid extension was found.");
return { baseName, config };
}

async function convertInput(filePath: string) {
const { fullPath, fileName, extension } = getFilePathNameExt(filePath);

const convertedJson = await readInputFile(extension, filePath);
function convertConfig(config: PolkadotLaunch.LaunchConfig): ZombienetConfig {
const relaychain = convertRelaychain(config.relaychain);
const parachains = convertParachains(
config.simpleParachains,
config.parachains,
);
const hrmpChannels = convertHrmpChannels(config.hrmpChannels);

const {
return {
relaychain,
parachains = [],
simpleParachains = [],
hrmpChannels = [],
types,
} = convertedJson;
parachains,
hrmp_channels: hrmpChannels,
types: config.types,
};
}

const nodes: NodeConfig[] = [];
let paras: ParachainConfig[] = [];
function convertRelaychain(
relaychain: PolkadotLaunch.LaunchConfig["relaychain"],
): ZombienetConfig["relaychain"] {
const { chain, genesis, nodes = [], bin } = relaychain;

const DEFAULT_NODE_VALUES = {
const convertedNodes = nodes.map((node) => ({
name: node.name,
args: node.flags,
ws_port: node.wsPort,
rpc_port: node.rpcPort,
p2p_port: node.port,
balance: DEFAULT_BALANCE,
validator: true,
invulnerable: true,
balance: DEFAULT_BALANCE,
}));

return {
chain,
default_command: bin,
genesis,
nodes: convertedNodes,
};
}

paras = paras.concat(
parachains.map(({ id, nodes }) => ({
id,
collators: ((nodes as PL_NodesConfig[]) || []).map(({ name }) => ({
name,
command: "adder-collator",
...DEFAULT_NODE_VALUES,
})),
})),
function convertParachains(
simpleParachains: PolkadotLaunch.LaunchConfig["simpleParachains"] = [],
parachains: PolkadotLaunch.LaunchConfig["parachains"] = [],
): ZombienetConfig["parachains"] {
const convertedSimpleParachains = simpleParachains.map(
convertSimpleParachain,
);
const convertedParachains = parachains.map(convertParachain);

paras = paras.concat(
simpleParachains.map(({ id, name }) => ({
id,
collators: [{ name, command: "adder-collator", ...DEFAULT_NODE_VALUES }],
})),
);
return convertedSimpleParachains.concat(convertedParachains);
}

if (relaychain?.nodes) {
relaychain.nodes.forEach((n: any) => {
nodes.push({
name: `"${n.name}"`,
...DEFAULT_NODE_VALUES,
});
});
}
function convertSimpleParachain(
simpleParachain: ArrayElement<
PolkadotLaunch.LaunchConfig["simpleParachains"]
>,
): ArrayElement<ZombienetConfig["parachains"]> {
const { id, balance, port, bin } = simpleParachain;

const jsonOutput: PolkadotLaunchConfig = {
relaychain: {
default_image: "docker.io/paritypr/polkadot-debug:master",
default_command: "polkadot",
default_args: ["-lparachain=debug"],
chain: relaychain?.chain || "",
nodes,
genesis: relaychain?.genesis,
},
types,
hrmp_channels: hrmpChannels,
parachains: paras,
const collator = {
name: "alice",
command: bin,
p2p_port: +port,
balance: +balance || DEFAULT_BALANCE,
validator: true,
invulnerable: true,
};

fs.writeFile(
`${fullPath}/${fileName}-zombienet.json`,
JSON.stringify(jsonOutput),
(error: any) => {
if (error) throw error;
},
return { id: +id, collators: [collator] };
}

function convertParachain(
parachain: ArrayElement<PolkadotLaunch.LaunchConfig["parachains"]>,
): ArrayElement<ZombienetConfig["parachains"]> {
const { id = "2000", balance, chain, nodes, bin } = parachain;

const collators = nodes.map(
({ name = "", flags, rpcPort, wsPort, port }) => ({
name,
command: bin,
args: flags,
ws_port: wsPort,
rpc_port: rpcPort,
p2p_port: port,
balance: +balance || DEFAULT_BALANCE,
validator: true,
invulnerable: true,
}),
);
console.log(
`Converted JSON config exists now under: ${fullPath}/${fileName}-zombienet.json`,

return { id: +id, chain, collators };
}

function convertHrmpChannels(
hrmpChannels: PolkadotLaunch.LaunchConfig["hrmpChannels"],
): ZombienetConfig["hrmp_channels"] {
return hrmpChannels.map(
({ sender, recipient, maxCapacity, maxMessageSize }) => ({
sender,
recipient,
max_capacity: maxCapacity,
max_message_size: maxMessageSize,
}),
);
}

async function persistConfig(config: ZombienetConfig, baseName: string) {
const content = JSON.stringify(config);
const path = `${baseName}-zombienet.json`;

await fs.writeFile(path, content);
console.log(`Converted JSON config exists now under: ${path}`);
}
94 changes: 65 additions & 29 deletions javascript/packages/cli/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,70 @@
import type { HrmpChannelsConfig, ObjectJSON } from "@zombienet/orchestrator";
// eslint-disable-next-line
export namespace PolkadotLaunch {
export interface LaunchConfig {
relaychain: RelayChainConfig;
parachains: ParachainConfig[];
simpleParachains: SimpleParachainConfig[];
hrmpChannels: HrmpChannelsConfig[];
types: any;
finalization: boolean;
}

// Config interfaces
export interface PL_NodesConfig {
name: string;
wsPort: number;
port: number;
flags?: [string];
}
export interface RelayChainConfig {
bin: string;
chain: string;
nodes: {
name: string;
basePath?: string;
wsPort: number;
rpcPort?: number;
nodeKey?: string;
port: number;
flags?: string[];
}[];
genesis?: JSON | ObjectJSON;
}

export interface PL_RelayChainConfig {
bin?: string;
chain: string;
nodes: [PL_NodesConfig];
genesis?: JSON | ObjectJSON;
}
export interface ParachainConfig {
bin: string;
id?: string;
balance: string;
chain?: string;
nodes: ParachainNodeConfig[];
}

export interface PL_ParaChainConfig {
bin?: string;
name?: string;
id: number;
port?: string;
balance?: string;
nodes: [PL_NodesConfig];
}
export interface ParachainNodeConfig {
rpcPort?: number;
wsPort: number;
port: number;
basePath?: string;
name?: string;
flags: string[];
}

export interface SimpleParachainConfig {
bin: string;
id: string;
port: string;
balance: string;
}

export interface HrmpChannelsConfig {
sender: number;
recipient: number;
maxCapacity: number;
maxMessageSize: number;
}

export interface CollatorOptions {
name?: string;
spec?: string;
flags?: string[];
basePath?: string;
chain?: string;
onlyOneParachainNode?: boolean;
}

export interface PL_ConfigType {
relaychain?: PL_RelayChainConfig;
parachains?: [PL_ParaChainConfig];
simpleParachains?: [PL_NodesConfig & { id: number }];
hrmpChannels?: HrmpChannelsConfig[];
types?: any;
finalization?: boolean;
export interface ObjectJSON {
[key: string]: ObjectJSON | number | string;
}
}

0 comments on commit 3254cbf

Please sign in to comment.