@moonsong-labs/moonwall-cli
Version:
Testing framework for the Moon family of projects
224 lines (221 loc) • 7.05 kB
JavaScript
import {
parseChopsticksRunCmd,
parseRunCmd
} from "./chunk-XIBPDQIU.js";
import {
launchNode
} from "./chunk-CY4QSJCG.js";
import {
populateProviderInterface,
prepareProviders
} from "./chunk-75ODDMN6.js";
import {
importJsonConfig
} from "./chunk-3P647NU6.js";
import {
__publicField
} from "./chunk-7B2TVWXJ.js";
// src/lib/globalContext.ts
import "@moonbeam-network/api-augment";
import Debug from "debug";
var debugSetup = Debug("global:context");
var _MoonwallContext = class {
environment;
providers;
nodes;
foundation;
_finalizedHead;
rtUpgradePath;
constructor(config) {
this.environment;
this.providers = [];
this.nodes = [];
const env = config.environments.find(({ name }) => name == process.env.MOON_TEST_ENV);
const blob = {
name: env.name,
context: {},
providers: [],
nodes: [],
foundationType: env.foundation.type
};
switch (env.foundation.type) {
case "read_only":
if (!env.connections) {
throw new Error(
`${env.name} env config is missing connections specification, required by foundation READ_ONLY`
);
} else {
blob.providers = prepareProviders(env.connections);
}
debugSetup(`\u{1F7E2} Foundation "${env.foundation.type}" parsed for environment: ${env.name}`);
break;
case "chopsticks":
blob.nodes.push(parseChopsticksRunCmd(env.foundation.launchSpec));
blob.providers.push(...prepareProviders(env.connections));
this.rtUpgradePath = env.foundation.rtUpgradePath;
debugSetup(`\u{1F7E2} Foundation "${env.foundation.type}" parsed for environment: ${env.name}`);
break;
case "dev":
const { cmd, args, launch } = parseRunCmd(env.foundation.launchSpec[0]);
blob.nodes.push({
name: env.foundation.launchSpec[0].name,
cmd,
args,
launch
});
blob.providers = env.connections ? prepareProviders(env.connections) : prepareProviders([
{
name: "w3",
type: "web3",
endpoints: [
`ws://127.0.0.1:${1e4 + Number(process.env.VITEST_POOL_ID || 1) * 100}`
]
},
{
name: "eth",
type: "ethers",
endpoints: [
`ws://127.0.0.1:${1e4 + Number(process.env.VITEST_POOL_ID || 1) * 100}`
]
},
{
name: "mb",
type: "moon",
endpoints: [
`ws://127.0.0.1:${1e4 + Number(process.env.VITEST_POOL_ID || 1) * 100}`
]
}
]);
debugSetup(`\u{1F7E2} Foundation "${env.foundation.type}" parsed for environment: ${env.name}`);
break;
default:
debugSetup(`\u{1F6A7} Foundation "${env.foundation.type}" unsupported, skipping`);
return;
}
this.environment = blob;
}
get genesis() {
if (this._finalizedHead) {
return this._finalizedHead;
} else {
return "";
}
}
set genesis(hash) {
if (hash.length !== 66) {
throw new Error("Cannot set genesis to invalid hash");
}
this._finalizedHead = hash;
}
async startNetwork() {
const activeNodes = this.nodes.filter((node) => !node.killed);
if (activeNodes.length > 0) {
console.log("Nodes already started! Skipping command");
return _MoonwallContext.getContext();
}
const nodes = _MoonwallContext.getContext().environment.nodes;
const promises = nodes.map(async ({ cmd, args, name, launch }) => {
return launch && this.nodes.push(await launchNode(cmd, args, name));
});
await Promise.all(promises);
}
async stopNetwork() {
if (this.nodes.length === 0) {
console.log("Nodes already stopped! Skipping command");
return _MoonwallContext.getContext();
}
this.nodes.forEach((node) => node.kill());
await this.wipeNodes();
}
async connectEnvironment(environmentName) {
if (this.providers.length > 0) {
console.log("Providers already connected! Skipping command");
return _MoonwallContext.getContext();
}
const globalConfig = await importJsonConfig();
const promises = this.environment.providers.map(
async ({ name, type, connect }) => new Promise(async (resolve) => {
this.providers.push(await populateProviderInterface(name, type, connect));
resolve("");
})
);
await Promise.all(promises);
this.foundation = globalConfig.environments.find(
({ name }) => name == environmentName
).foundation.type;
if (this.foundation == "dev") {
this.genesis = (await this.providers.find(({ type }) => type == "polkadotJs" || type == "moon").api.rpc.chain.getBlockHash(0)).toString();
}
if (this.foundation == "chopsticks") {
this.genesis = (await this.providers.find(({ type }) => type == "polkadotJs" || type == "moon").api.rpc.chain.getFinalizedHead()).toString();
}
}
async wipeNodes() {
this.nodes = [];
}
async disconnect(providerName) {
if (providerName) {
this.providers.find(({ name }) => name === providerName).disconnect();
this.providers.filter(({ name }) => name !== providerName);
} else {
await Promise.all(this.providers.map((prov) => prov.disconnect()));
this.providers = [];
}
}
static printStats() {
if (_MoonwallContext) {
console.dir(_MoonwallContext.getContext(), { depth: 1 });
} else {
console.log("Global context not created!");
}
}
static getContext(config, force = false) {
if (!_MoonwallContext.instance || force) {
if (global.moonInstance && !force) {
_MoonwallContext.instance = global.moonInstance;
return _MoonwallContext.instance;
}
if (!config) {
console.error("\u274C Config must be provided on Global Context instantiation");
return void 0;
}
_MoonwallContext.instance = new _MoonwallContext(config);
debugSetup(`\u{1F7E2} Moonwall context "${config.label}" created`);
}
return _MoonwallContext.instance;
}
static async destroy() {
const ctx = _MoonwallContext.getContext();
try {
ctx.disconnect();
} catch {
console.log("\u{1F6D1} All connections disconnected");
}
const promises = ctx.nodes.map((process2) => {
return new Promise((resolve) => {
process2.kill();
if (process2.killed) {
resolve(`process ${process2.pid} killed`);
}
});
});
await Promise.all(promises);
}
};
var MoonwallContext = _MoonwallContext;
__publicField(MoonwallContext, "instance");
var contextCreator = async (config, env) => {
const ctx = MoonwallContext.getContext(config);
await runNetworkOnly(config);
await ctx.connectEnvironment(env);
return ctx;
};
var runNetworkOnly = async (config) => {
const ctx = MoonwallContext.getContext(config);
await ctx.startNetwork();
};
export {
MoonwallContext,
contextCreator,
runNetworkOnly
};