@taqueria/node-sdk
Version:
A TypeScript SDK for NodeJS used for Taqueria plugin development.
671 lines (669 loc) • 23.7 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 { 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