UNPKG

@taqueria/node-sdk

Version:

A TypeScript SDK for NodeJS used for Taqueria plugin development.

671 lines (669 loc) • 23.7 kB
import { PluginSchema, __require } from "./chunk-WHSIYNQJ.mjs"; // index.ts export * from "@taqueria/protocol/types"; import * as Protocol from "@taqueria/protocol"; import { quote as shellEscape } from "shell-quote"; import { Config, EconomicalProtocolHash, Environment, Faucet, LoadedConfig, NetworkConfig, NonEmptyString as NonEmptyString2, Option, PositionalArg, ProxyTaskArgs as ProxyTaskArgs2, ProxyTemplateArgs as ProxyTemplateArgs2, RequestArgs as RequestArgs2, Task } from "@taqueria/protocol"; import * as Template from "@taqueria/protocol/Template"; import load from "@taqueria/protocol/i18n"; import * as SHA256 from "@taqueria/protocol/SHA256"; import { E_TaqError, toFutureParseErr, toFutureParseUnknownErr } from "@taqueria/protocol/TaqError"; import { readJsonFileInterceptConfig, writeJsonFileInterceptConfig } from "@taqueria/protocol/types-config-files"; import { exec, spawn } from "child_process"; import { mapRej, promise } from "fluture"; import { readFile, writeFile } from "fs/promises"; import { dirname, join, resolve as resolvePath } from "path"; import { getSync } from "stacktrace-js"; import { ZodError } from "zod"; import { InMemorySigner } from "@taquito/signer"; import { importKey, TezosToolkit } from "@taquito/taquito"; import { b58Encode, PrefixV2 } from "@taquito/utils"; import * as Bip39 from "bip39"; import crypto from "crypto"; var yargs = __require("yargs"); var TAQ_OPERATOR_ACCOUNT = "taqOperatorAccount"; var eager = (f) => promise( mapRej((err) => new E_TaqError(err))(f) ); var writeJsonFileInner = (filename) => (data) => writeFile(filename, JSON.stringify(data, void 0, 4), { encoding: "utf8" }).then((_) => filename); var writeJsonFile = writeJsonFileInterceptConfig(writeJsonFileInner); var readJsonFileInner = (filename) => readFile(filename, { encoding: "utf-8" }).then(JSON.parse).then((result) => result); var readJsonFile = readJsonFileInterceptConfig(readJsonFileInner); var readJsonFileWithoutTransform = readJsonFileInner; var filterDockerImageMessages = (stderr) => { let skip = false; const filteredStderr = stderr.split("\n").filter((line) => { if (line.startsWith("Unable to find image")) { skip = true; } if (skip && line.startsWith("Downloaded newer image")) { skip = false; return false; } return !skip; }).join("\n"); return filteredStderr; }; var execCmd = (cmd, stdErrFilter) => new Promise((resolve, reject) => { const escapedCmd = cmd.replaceAll(/"/gm, '\\"'); exec(`sh -c "${escapedCmd}"`, (err, stdout, stderr) => { const customFiltered = stdErrFilter ? stdErrFilter(stderr) : stderr; const filteredStderr = filterShellCmdStderr(customFiltered); if (err) { reject(toExecErr(err, { stderr: filteredStderr, stdout })); } else { resolve({ stdout, stderr: filteredStderr }); } }); }); var filterNPMWarnings = (stderr) => stderr.split("\n").filter((line) => !/npm\s+warn/i.test(line)).join("\n"); var filterShellCmdStderr = (stderr) => { let retval = filterDockerImageMessages(stderr); retval = filterNPMWarnings(retval); retval = filterOctezWarningMessages(retval); return retval; }; var filterOctezWarningMessages = (stderr) => { return stderr.split("\n").filter((line) => !line.trim().startsWith("Warning:")).filter((line) => !line.includes("This is NOT the Tezos Mainnet.")).filter((line) => !line.includes("Do NOT use your fundraiser keys on this network.")).join("\n").trim(); }; var toExecErr = (message, props) => { const err = message instanceof Error ? message : new Error(message); const retval = err; retval.stderr = props.stderr; retval.stdout = props.stdout; return retval; }; var execCommandWithoutWrapping = (cmd) => new Promise((resolve, reject) => { exec(cmd, (err, stdout, stderr) => { if (err) reject(err); else { resolve({ stdout, stderr }); } }); }); var spawnCmd = (cmd, envVars = {}) => new Promise((resolve, reject) => { const child = spawn(cmd, { env: { ...process.env, ...envVars }, stdio: "inherit", shell: true }); child.on("close", resolve); child.on("error", reject); }); var getArchSync = () => { switch (process.arch) { case "arm64": return "linux/arm64/v8"; // @ts-ignore: x32 is valid for some versions of NodeJS case "x32": case "x64": return "linux/amd64"; default: const err = { kind: "E_INVALID_ARCH", msg: `The ${process.arch} architecture is not supported at this time.`, context: process.arch }; throw err; } }; var getArch = () => new Promise((resolve, reject) => { try { const arch = getArchSync(); resolve(arch); } catch (e) { reject(e); } }); var parseJSON = (input) => new Promise((resolve, reject) => { try { const json = JSON.parse(input); resolve(json); } catch (previous) { const taqErr = { kind: "E_INVALID_JSON", msg: `Invalid JSON: ${input}`, previous, context: input }; return reject(taqErr); } }); var sendRes = (msg, newline = true) => { if (!msg || msg.length === 0) return; const output = newline ? msg + "\n" : msg; return process.stdout.write(output); }; var sendAsyncRes = (msg, newline = true) => Promise.resolve(sendRes(msg, newline)); var sendErr = (msg, newline = true) => { if (!msg || msg.length === 0) return; const output = newline ? msg + "\n" : msg; process.stderr.write(output); return output; }; var sendWarn = (msg, newline = true) => { if (!msg || msg.length === 0) return; const output = newline ? msg + "\n" : msg; process.stderr.write(output); return output; }; var sendAsyncErr = (msg, newline = true) => Promise.reject(sendErr(msg, newline)); var sendJson = (msg, newline = true) => sendRes(JSON.stringify(msg), newline); var sendJsonErr = (msg, newline = true) => sendErr(JSON.stringify(msg), newline); var sendAsyncJson = (msg, newline = true) => sendAsyncRes(JSON.stringify(msg), newline); var sendAsyncJsonErr = (msg, newline = true) => sendAsyncErr(JSON.stringify(msg), newline); var sendJsonRes = (data, messages) => typeof data === "object" ? sendJson({ data, render: "table", messages }) : sendJson({ data, render: "string", messages }); var sendAsyncJsonRes = (data) => Promise.resolve(sendJsonRes(data)).then(() => { }); var noop = () => { }; var parseArgs = (unparsedArgs) => { if (unparsedArgs && Array.isArray(unparsedArgs) && unparsedArgs.length >= 2) { try { const preprocessedArgs = preprocessArgs(unparsedArgs); const argv = yargs(preprocessedArgs.slice(2)).argv; const postprocessedArgs = postprocessArgs(argv); const formattedArgs = formatArgs(postprocessedArgs); const requestArgs = Protocol.RequestArgs.from(formattedArgs); return Promise.resolve(requestArgs); } catch (previous) { if (previous instanceof ZodError) { return eager( toFutureParseErr(previous, "The plugin request arguments are invalid", unparsedArgs) ); } return eager( toFutureParseUnknownErr( previous, "There was a problem trying to parse the plugin request arguments", unparsedArgs ) ); } } return Promise.reject("Invalid usage. If you were testing your plugin, did you remember to specify --taqRun?"); }; var preprocessArgs = (args) => { return args.map((arg) => /^0x[0-9a-fA-F]+$/.test(arg) ? "___" + arg + "___" : arg); }; var getSelectedEnvironment = (args) => args.env ? args.env : args.config.environment["default"] ?? "development"; var formatArgs = (args) => { const entries = Object.entries(args).map( ([key, value]) => { if (key === "config") return [key, JSON.parse(value)]; else if (value === "false") return [key, false]; else if (value === "true") return [key, true]; return [key, value]; } ); const formatted = Object.fromEntries(entries); return { ...formatted, env: getSelectedEnvironment(formatted) }; }; var postprocessArgs = (args) => { const postprocessedArgs = Object.entries(args).map(([key, val]) => [ key, typeof val === "string" && /^___0x[0-9a-fA-F]+___$/.test(val) ? val.slice(3, -3) : val ]); const groupedArgs = postprocessedArgs.reduce( (acc, arg) => { const key = arg[0]; const val = arg[1]; return { ...acc, [key]: val }; }, {} ); return groupedArgs; }; var parseSchema = (i18n, definer, defaultPluginName, requestArgs) => { const inputSchema = definer(requestArgs, i18n); const { proxy } = inputSchema; const pluginInfo = PluginSchema.create({ ...inputSchema, name: inputSchema.name ?? defaultPluginName }); return { ...pluginInfo, proxy }; }; var toProxableArgs = (requestArgs, from) => { const retval = Object.entries(requestArgs).reduce( (retval2, [key, value]) => { if (key === "projectDir") value = resolvePath(String(value).toString()); else if (typeof value === "string") { if (value === "true") value = true; else if (value === "false") value = false; else if (key === "config") value = JSON.parse(value); } const proxyArgs = { ...retval2, ...Object.fromEntries([[key, value]]) }; return proxyArgs; }, {} ); return from(retval); }; var getResponse = (definer, defaultPluginName) => async (requestArgs) => { var _a; const { taqRun } = requestArgs; const i18n = await load(); const schema = parseSchema(i18n, definer, defaultPluginName, requestArgs); try { switch (taqRun) { case "pluginInfo": { const output = { ...schema, templates: schema.templates ? schema.templates.map( (template) => { const handler = typeof template.handler === "function" ? "function" : template.handler; return { ...template, handler }; } ) : [], tasks: schema.tasks ? schema.tasks.map( (task) => { const handler = typeof task.handler === "function" ? "function" : task.handler; return { ...task, handler }; } ) : [], proxy: true, checkRuntimeDependencies: schema.checkRuntimeDependencies ? true : false, installRuntimeDependencies: schema.installRuntimeDependencies ? true : false }; return sendAsyncJson(output); } case "proxy": if (schema.proxy) { return schema.proxy(toProxableArgs(requestArgs, Protocol.ProxyTaskArgs.from.bind(Protocol.ProxyTaskArgs))); } return Promise.reject({ errCode: "E_NOT_SUPPORTED", message: i18n.__("proxyNotSupported"), context: requestArgs }); case "proxyTemplate": { const proxyArgs = toProxableArgs( requestArgs, Protocol.ProxyTemplateArgs.from.bind(Protocol.ProxyTemplateArgs) ); const template = (_a = schema.templates) == null ? void 0 : _a.find((tmpl) => tmpl.template === proxyArgs.template); if (template) { if (typeof template.handler === "function") { return await template.handler(proxyArgs); } return Promise.reject({ errCode: "E_NOT_SUPPORTED", message: i18n.__("proxyNotSupported"), context: requestArgs }); } return Promise.reject({ errCode: "E_INVALID_TEMPLATE", message: i18n.__("invalidTemplate"), context: requestArgs }); } case "runPostInstall": if (schema.postInstall) { const schemaArg = shellEscape([JSON.stringify({ name: schema.name ?? "unknown", alias: schema.alias, version: schema.version, schema: schema.schema })]); const result = await execCmd(`${schema.postInstall} ${schemaArg}`); if (result.stderr) { return sendAsyncErr("\n" + result.stderr); } return sendAsyncRes("\n" + result.stdout); } return Promise.resolve({}); break; // case 'checkRuntimeDependencies': // return sendAsyncJson( // schema.checkRuntimeDependencies // ? schema.checkRuntimeDependencies(requestArgs) // : Promise.resolve({ report: [] }), // ); // case 'installRuntimeDependencies': // return sendAsyncJson( // schema.installRuntimeDependencies // ? schema.installRuntimeDependencies(requestArgs) // : Promise.resolve({ report: [] }), // ); default: return Promise.reject({ errCode: "E_NOT_SUPPORTED", message: i18n.__("actionNotSupported"), context: requestArgs }); } } catch (previous) { return Promise.reject({ errCode: "E_UNEXPECTED", message: "The plugin encountered a fatal error", previous }); } }; var getNameFromPluginManifest = (packageJsonAbspath) => { try { return `${__require(packageJsonAbspath).name}`; } catch (_) { return getGeneratedPackageName(packageJsonAbspath); } }; var getGeneratedPackageName = (packageJsonAbsPath) => { const chunks = packageJsonAbsPath.split("/"); chunks.pop(); return chunks.pop() ?? "unknown-plugin"; }; var getCurrentEnvironment = (parsedArgs) => { return parsedArgs.env ? parsedArgs.env : parsedArgs.config.environment ? parsedArgs.config.environment.default : "development"; }; var getFaucetUrl = (networkName) => { const knownTestnets = ["shadownet", "ghostnet", "weeklynet", "dailynet"]; const lowerName = networkName.toLowerCase(); const match = knownTestnets.find((net) => lowerName.includes(net)); return match ? `https://faucet.${match}.teztnets.com` : "https://teztnets.com"; }; var getCurrentEnvironmentConfig = (parsedArgs) => { const currentEnv = getCurrentEnvironment(parsedArgs); return parsedArgs.config.environment && parsedArgs.config.environment[currentEnv] ? parsedArgs.config.environment[currentEnv] : void 0; }; var getMetadataConfig = (parsedArgs) => () => parsedArgs.config.metadata ?? void 0; var getNetworkConfig = (parsedArgs) => (networkName) => parsedArgs.config.network[networkName] ?? void 0; var getSandboxConfig = (parsedArgs) => (sandboxName) => parsedArgs.config.sandbox[sandboxName] ?? void 0; var getSandboxAccountNames = (parsedArgs) => (sandboxName) => { const sandbox = getSandboxConfig(parsedArgs)(sandboxName); return sandbox ? Object.keys(sandbox.accounts ?? []).filter((accountName) => accountName !== "default") : []; }; var getSandboxAccountConfig = (sandbox, accountName) => { if (sandbox.accounts) { const accounts = sandbox.accounts; return accounts[accountName]; } return void 0; }; var addTzExtensionIfMissing = (contractFilename) => /\.tz$/.test(contractFilename) ? contractFilename : `${contractFilename}.tz`; var getArtifactsDir = (parsedArgs) => parsedArgs.config.artifactsDir ?? "artifacts"; var getContractsDir = (parsedArgs) => parsedArgs.config.contractsDir ?? "contracts"; var getContractContent = async (parsedArgs, contractFilename) => { const contractWithTzExtension = addTzExtensionIfMissing(contractFilename); const contractPath = join(parsedArgs.config.projectDir, getArtifactsDir(parsedArgs), contractWithTzExtension); try { const content = await readFile(contractPath, { encoding: "utf-8" }); return content; } catch (err) { sendErr(`Could not read ${contractPath}. Maybe it doesn't exist. `); return void 0; } }; var getParameter = async (parsedArgs, paramFilename) => { const paramPath = join(parsedArgs.config.projectDir, parsedArgs.config.artifactsDir ?? "artifacts", paramFilename); try { const content = await readFile(paramPath, { encoding: "utf-8" }); return content; } catch (err) { return sendAsyncErr(`Could not read ${paramPath}. Maybe it doesn't exist.`); } }; var updateAddressAlias = async (parsedArgs, alias, address) => { const env = getCurrentEnvironmentConfig(parsedArgs); if (!env) return; if (!env.aliases) { env.aliases = { [alias]: { address } }; } else if (!env.aliases[alias]) { env.aliases[alias] = { address }; } else { env.aliases[alias].address = address; } try { await writeJsonFile(parsedArgs.config.configFile)(parsedArgs.config); } catch (err) { sendErr(`Could not write to ${parsedArgs.config.configFile} `); } }; var getAddressOfAlias = async (env, alias) => { var _a, _b; const address = (_b = (_a = env.aliases) == null ? void 0 : _a[alias]) == null ? void 0 : _b.address; if (!address) { return sendAsyncErr( `Address for alias "${alias}" is not present in the config.json. Make sure to deploy a contract with such alias.` ); } return address; }; var getAccountPrivateKey = async (parsedArgs, network, account) => { var _a, _b; if (!network.accounts) network.accounts = {}; if (!network.accounts[account] || !network.accounts[account].privateKey) { const mnemonic = ((_b = (_a = network == null ? void 0 : network.accounts) == null ? void 0 : _a[account]) == null ? void 0 : _b.mnemonic) ?? Bip39.generateMnemonic(); const signer = InMemorySigner.fromMnemonic({ mnemonic }); const tezos = new TezosToolkit(network.rpcUrl); tezos.setSignerProvider(signer); const publicKey = Protocol.NonEmptyString.create(await tezos.signer.publicKey()); const publicKeyHash = Protocol.PublicKeyHash.create(await tezos.signer.publicKeyHash()); const privateKey2 = Protocol.NonEmptyString.create(await tezos.signer.secretKey() ?? ""); if (!privateKey2) return sendAsyncErr("The private key must exist after creating it"); network.accounts[account] = Protocol.NetworkAccountConfig.create({ publicKey, publicKeyHash, privateKey: privateKey2, mnemonic }); try { await writeJsonFile("./.taq/config.json")(parsedArgs.config); } catch (err) { return sendAsyncErr(`Could not write to ./.taq/config.json `); } if (account === TAQ_OPERATOR_ACCOUNT) { const faucetUrl = getFaucetUrl(network.label); return sendAsyncErr( `A keypair with public key hash ${network.accounts[account].publicKeyHash} was generated for you. To fund this account: 1. Go to ${faucetUrl} 2. Copy and paste the above key into the wallet address field 3. Request some Tez (Note that you might need to wait for a few seconds for the network to register the funds) Alternatively, use --sender <accountAlias> if you have an already-funded account.` ); } } const privateKey = network.accounts[account].privateKey; if (!privateKey) return sendAsyncErr("The private key must exist after creating it"); return privateKey; }; var getDockerImage = (defaultImageName, envVarName) => process.env[envVarName] ?? defaultImageName; var getDefaultSandboxAccount = (sandbox) => { const accounts = sandbox.accounts ?? {}; const defaultAccount = accounts["default"]; if (defaultAccount) return getSandboxAccountConfig(sandbox, defaultAccount); return void 0; }; var getContracts = (regex, config) => { if (!config.contracts) return []; return Object.entries(config.contracts).reduce( (retval, [_, contract]) => { if (contract && typeof contract === "object" && "sourceFile" in contract && typeof contract.sourceFile === "string") { return regex.test(contract.sourceFile) ? [...retval, contract.sourceFile] : retval; } return retval; }, [] ); }; var joinPaths = (...paths) => paths.join("/"); var stringToSHA256 = (s) => SHA256.toSHA256(s); var getPackageName = () => { const stack = getSync({ filter: ((stackFrame) => { const filename = stackFrame.getFileName(); return !filename.includes("taqueria-sdk") && !filename.includes("@taqueria/node-sdk") && !filename.includes("stacktrace-js"); }) }); const frame = stack.shift(); if (frame) { const filename = frame.getFileName().replace(/^file:\/\//, "").replace(/^file:/, ""); const pluginManifest = join(dirname(filename), "package.json"); return getNameFromPluginManifest(pluginManifest); } return getGeneratedPackageName(""); }; var isTaqError = (err) => { return err.kind !== void 0; }; var sanitizedStderrWriter = () => { const stream = __require("stream"); const { Console } = __require("console"); const writable = stream.Writable({ write(chunk, _encoding, next) { console.error(chunk.toString("utf8").replaceAll(/("[^"]+key\"):("[^"]+\")/gi, `$1:"[hidden]"`)); next(); } }); return new Console(process.stdout, writable); }; var outputSanitizedErr = (err) => { const console2 = sanitizedStderrWriter(); console2.error(err); }; var Plugin = { create: (definer, unparsedArgs) => { const packageName = getPackageName(); return parseArgs(unparsedArgs).then(getResponse(definer, packageName)).catch((err) => { if (err) { const debug = unparsedArgs.join(",").includes(["--debug", true].join(",")); if (isTaqError(err) && err.kind === "E_PARSE" && err.previous && err.previous instanceof ZodError) { const msgs = err.previous.errors.reduce( (retval, issue) => { const path = issue.path.join(" \u2192 "); const msg = ` ${path}: ${issue.message}`; return [...retval, msg]; }, [`Taqueria tried to send data to ${packageName} that it couldn't parse or understand. This is most likely due to the version of the plugin being out-of-date and incompatible with the CLI or vice versa. More details:`] ); console.error(msgs.join("\n") + "\n"); } else if (typeof err === "string") console.error(err); else if (!debug && typeof err !== "boolean") { console.error(`${packageName} encountered an unexpected problem. Use --debug to learn more.`); } if (debug) { outputSanitizedErr(err); } } process.exit(1); }).then(() => { setTimeout(() => process.exit(0), 200); }); } }; var isContractFile = (filename) => { return !filename.includes(".default_storage.") && !filename.includes(".storage.") && !filename.includes(".parameter.") && !filename.includes(".expression."); }; export { Config, EconomicalProtocolHash, Environment, Faucet, LoadedConfig, NetworkConfig, NonEmptyString2 as NonEmptyString, Option, Plugin, PositionalArg, Protocol, ProxyTaskArgs2 as ProxyTaskArgs, ProxyTemplateArgs2 as ProxyTemplateArgs, RequestArgs2 as RequestArgs, TAQ_OPERATOR_ACCOUNT, Task, Template, addTzExtensionIfMissing, eager, execCmd, execCommandWithoutWrapping, getAccountPrivateKey, getAddressOfAlias, getArch, getArchSync, getArtifactsDir, getContractContent, getContracts, getContractsDir, getCurrentEnvironment, getCurrentEnvironmentConfig, getDefaultSandboxAccount, getDockerImage, getFaucetUrl, getMetadataConfig, getNetworkConfig, getParameter, getSandboxAccountConfig, getSandboxAccountNames, getSandboxConfig, getSelectedEnvironment, isContractFile, isTaqError, joinPaths, noop, parseJSON, readJsonFile, readJsonFileWithoutTransform, sendAsyncErr, sendAsyncJson, sendAsyncJsonErr, sendAsyncJsonRes, sendAsyncRes, sendErr, sendJson, sendJsonErr, sendJsonRes, sendRes, sendWarn, spawnCmd, stringToSHA256, toExecErr, updateAddressAlias, writeJsonFile }; //# sourceMappingURL=index.mjs.map