@taqueria/node-sdk
Version:
A TypeScript SDK for NodeJS used for Taqueria plugin development.
661 lines (660 loc) • 23.3 kB
JavaScript
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 { importKey, InMemorySigner } from "@taquito/signer";
import { TezosToolkit } from "@taquito/taquito";
import { b58cencode, Prefix, prefix } 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 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) {
return sendAsyncErr(
`A keypair with public key hash ${network.accounts[account].publicKeyHash} was generated for you.
To fund this account:
1. Go to https://teztnets.xyz and click "Faucet" of the target testnet
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)`
);
}
}
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,
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