UNPKG

create-tezos-smart-contract

Version:

Node.js toolset to write, test and deploy Tezos smart contracts

199 lines (198 loc) 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isFlextesaRunning = exports.stopFlextesa = exports.startFlextesa = exports.POD_NAME = void 0; const child_process_1 = require("child_process"); const console_1 = require("../../console"); const config_1 = require("../config"); const docker_1 = require("../docker"); const tezos_1 = require("../tezos"); const parameters_1 = require("./parameters"); // Flextesa image const FLEXTESA_IMAGE = "oxheadalpha/flextesa:20220321"; // Name for the running Docker image exports.POD_NAME = 'flextesa-sandbox'; const defaultProtocol = tezos_1.TezosProtocols.GRANADA; const defaultOptions = config_1.defaultConfig.sandbox; // This is to avoid printing flextesa full-console in output const FLEXTESA_INPUT_COMMAND = "Flextesa: Please enter command:"; const FLEXTESA_MESSAGE_HEADER = /Flextesa:\n/igm; const FLEXTESA_WARNING = /.+(?<=warning:( )*(\n)*).+/igm; const FLEXTESA_ERROR = /.+(?<=(fatal-error:|error:)( )*(\n)*).+/igm; const FLEXTESA_EXIT = "Last pause before the application will Kill 'Em All and Quit."; const hasFlextesaMessage = (message) => { const hasHeader = message.match(FLEXTESA_MESSAGE_HEADER); return !!hasHeader && hasHeader.length > 0; }; const handleFlextesaMessages = (str) => { const message = str.replace(FLEXTESA_MESSAGE_HEADER, ''); if (message.includes(FLEXTESA_EXIT)) { (0, console_1.error)("Flextesa failed to start all the needed services, now forcing shutdown..."); // stopFlextesa(); return true; } const lines = message.split('\n'); const output = []; const l = (msg, fn) => ({ fn, msg }); let globalRenderer = console_1.debug; for (const line of lines) { const warnings = line.match(FLEXTESA_WARNING); const errors = line.match(FLEXTESA_ERROR); if (errors?.length) { for (const err of errors) { output.push(l(err, console_1.error)); } globalRenderer = console_1.error; } if (warnings?.length) { for (const warning of warnings) { output.push(l(warning, console_1.warn)); } if (globalRenderer !== console_1.error) { globalRenderer = console_1.warn; } } if (!warnings?.length && !errors?.length) { output.push(l(line)); } } for (const log of output) { const msg = log.msg.replace('\t', ''); if (log.fn) { log.fn(msg); } else { globalRenderer(msg); } } return false; }; const startFlextesa = async (_options, readyCallback) => { (0, console_1.log)(`Preparing Flextesa sandbox...`); const image = await (0, docker_1.ensureImageIsPresent)(FLEXTESA_IMAGE); if (!image) { (0, console_1.error)('Unable to find Flextesa image, compilation failed.'); return; } // Merge with defaults const options = Object.assign({}, defaultOptions, _options); // Localhost is not a valid host for Docker const host = options.host === "localhost" ? "0.0.0.0" : options.host; const port = options.port; // Protocol "validity" checks const protocol = (!options.protocol || !parameters_1.flextesaProtocols[options.protocol]) ? defaultProtocol : options.protocol; const accountsParams = (0, parameters_1.createAccountsParams)(options.accounts || {}); const tezosNodeParams = (0, parameters_1.createProtocolParams)(protocol); const args = [ "run", "-i", "--rm", "--name", exports.POD_NAME, "-p", host + ":" + port + ":20000", "--env", "flextesa_node_cors_origin=*", FLEXTESA_IMAGE, "flextesa", "mini-net", "--genesis-block-hash", options.genesisBlockHash, // "--remove-default-bootstrap-accounts" /** * Please don't use --remove-default-bootstrap-accounts in conjunction with * --no-daemons-for on every added account. This would have Flextesa not baking * anything, so the header block would be empty and Taquito does not really like it! */ "--time-between-blocks", "2", // "--minimal-block-delay", "1", "--pause-on-error=true", ...accountsParams, ...tezosNodeParams ]; const opts = {}; (0, console_1.debug)(`Starting Flextesa with these arguments:`); (0, console_1.debug)("docker " + args.join(' ')); const flextesa = (0, child_process_1.spawn)("docker", args, opts); let shouldStopLogging = false; // Setup listeners for errors and close listeners to handle crashed during Flextesa boot let stderr = ""; function onErrored(err) { (0, console_1.error)("Flextesa running failed with:", err.message); flextesa.removeListener("close", onClosed); (0, exports.stopFlextesa)(); throw err; } async function onClosed(code) { flextesa.removeListener("error", onErrored); if (await (0, exports.isFlextesaRunning)()) { (0, exports.stopFlextesa)(); } if (code !== 0) { (0, console_1.error)(`Flextesa exited with code ${code}.`); } } flextesa.on("error", onErrored); flextesa.on("close", onClosed); flextesa.stderr.on("data", function fn(data) { const str = data.toString(); stderr += str; if (shouldStopLogging) { stderr = ""; return; } // Print every message as it is, apart from flextesa warnings, errors and input command if (hasFlextesaMessage(str)) { shouldStopLogging = handleFlextesaMessages(str); } else if (str.indexOf(FLEXTESA_INPUT_COMMAND) == -1) { // Let docker lib handle warnings const hasWarnings = (0, docker_1.handleDockerWarnings)(str); // if warnings weren't there, just print the messages if (!hasWarnings) { (0, console_1.debug)(str); } } else { // But when we reach it, Flextsa is ready // eslint-disable-next-line @typescript-eslint/no-unused-vars stderr = ""; // unbind the now unused listeners for boot problems... flextesa.removeListener("close", onClosed); flextesa.removeListener("error", onErrored); flextesa.stderr.removeListener("data", fn); // Print general output flextesa.stdout.on("data", (data) => { (0, console_1.debug)(data.toString()); }); // Print standard flextesa output flextesa.stderr.on("data", (data) => { const str = data.toString(); (0, console_1.error)(str.replace(FLEXTESA_INPUT_COMMAND, "")); }); (0, console_1.em)(`Tezos sandbox is ready!`); if (readyCallback) { readyCallback(); } } }); }; exports.startFlextesa = startFlextesa; const stopFlextesa = (callback) => { try { (0, child_process_1.execSync)(`docker rm -f ${exports.POD_NAME}`); } catch (e) { (0, console_1.error)('Stopping Flextesa thrown:', e); } callback && callback(); }; exports.stopFlextesa = stopFlextesa; const isFlextesaRunning = async () => { try { const buffer = (0, child_process_1.execSync)(`docker ps -f name=${exports.POD_NAME} -q`); return buffer.length !== 0; } catch (e) { return false; } }; exports.isFlextesaRunning = isFlextesaRunning;