UNPKG

@nomiclabs/buidler

Version:

Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

233 lines 10.4 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const t = __importStar(require("io-ts")); const lib_1 = require("io-ts/lib"); const constants_1 = require("../../constants"); const errors_1 = require("../errors"); const errors_list_1 = require("../errors-list"); function stringify(v) { if (typeof v === "function") { return lib_1.getFunctionName(v); } if (typeof v === "number" && !isFinite(v)) { if (isNaN(v)) { return "NaN"; } return v > 0 ? "Infinity" : "-Infinity"; } return JSON.stringify(v); } function getContextPath(context) { const keysPath = context .slice(1) .map((c) => c.key) .join("."); return `${context[0].type.name}.${keysPath}`; } function getMessage(e) { const lastContext = e.context[e.context.length - 1]; return e.message !== undefined ? e.message : getErrorMessage(getContextPath(e.context), e.value, lastContext.type.name); } function getErrorMessage(path, value, expectedType) { return `Invalid value ${stringify(value)} for ${path} - Expected a value of type ${expectedType}.`; } function failure(es) { return es.map(getMessage); } exports.failure = failure; function success() { return []; } exports.success = success; exports.DotPathReporter = { report: (validation) => validation.fold(failure, success), }; function optional(codec, name = `${codec.name} | undefined`) { return new t.Type(name, (u) => u === undefined || codec.is(u), (u, c) => (u === undefined ? t.success(u) : codec.validate(u, c)), (a) => (a === undefined ? undefined : codec.encode(a))); } // IMPORTANT: This t.types MUST be kept in sync with the actual types. const BuidlerNetworkAccount = t.type({ privateKey: t.string, balance: t.string, }); const BuidlerNetworkConfig = t.type({ hardfork: optional(t.string), chainId: optional(t.number), from: optional(t.string), gas: optional(t.union([t.literal("auto"), t.number])), gasPrice: optional(t.union([t.literal("auto"), t.number])), gasMultiplier: optional(t.number), accounts: optional(t.array(BuidlerNetworkAccount)), blockGasLimit: optional(t.number), throwOnTransactionFailures: optional(t.boolean), throwOnCallFailures: optional(t.boolean), loggingEnabled: optional(t.boolean), allowUnlimitedContractSize: optional(t.boolean), initialDate: optional(t.string), }); const HDAccountsConfig = t.type({ mnemonic: t.string, initialIndex: optional(t.number), count: optional(t.number), path: optional(t.string), }); const OtherAccountsConfig = t.type({ type: t.string, }); const NetworkConfigAccounts = t.union([ t.literal("remote"), t.array(t.string), HDAccountsConfig, OtherAccountsConfig, ]); const HttpHeaders = t.record(t.string, t.string, "httpHeaders"); const HttpNetworkConfig = t.type({ chainId: optional(t.number), from: optional(t.string), gas: optional(t.union([t.literal("auto"), t.number])), gasPrice: optional(t.union([t.literal("auto"), t.number])), gasMultiplier: optional(t.number), url: optional(t.string), accounts: optional(NetworkConfigAccounts), httpHeaders: optional(HttpHeaders), }); const NetworkConfig = t.union([BuidlerNetworkConfig, HttpNetworkConfig]); const Networks = t.record(t.string, NetworkConfig); const ProjectPaths = t.type({ root: optional(t.string), cache: optional(t.string), artifacts: optional(t.string), sources: optional(t.string), tests: optional(t.string), }); const EVMVersion = t.string; const SolcOptimizerConfig = t.type({ enabled: optional(t.boolean), runs: optional(t.number), }); const SolcConfig = t.type({ version: optional(t.string), optimizer: optional(SolcOptimizerConfig), evmVersion: optional(EVMVersion), }); const AnalyticsConfig = t.type({ enabled: optional(t.boolean), }); const BuidlerConfig = t.type({ defaultNetwork: optional(t.string), networks: optional(Networks), paths: optional(ProjectPaths), solc: optional(SolcConfig), analytics: optional(AnalyticsConfig), }, "BuidlerConfig"); /** * Validates the config, throwing a BuidlerError if invalid. * @param config */ function validateConfig(config) { const errors = getValidationErrors(config); if (errors.length === 0) { return; } let errorList = errors.join("\n * "); errorList = ` * ${errorList}`; throw new errors_1.BuidlerError(errors_list_1.ERRORS.GENERAL.INVALID_CONFIG, { errors: errorList }); } exports.validateConfig = validateConfig; function getValidationErrors(config) { const errors = []; // These can't be validated with io-ts if (config !== undefined && typeof config.networks === "object") { const buidlerNetwork = config.networks[constants_1.BUIDLEREVM_NETWORK_NAME]; if (buidlerNetwork !== undefined) { if (buidlerNetwork.hardfork !== undefined && !constants_1.BUIDLEREVM_SUPPORTED_HARDFORKS.includes(buidlerNetwork.hardfork)) { errors.push(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.hardfork is not supported. Use one of ${constants_1.BUIDLEREVM_SUPPORTED_HARDFORKS.join(", ")}`); } if (buidlerNetwork.allowUnlimitedContractSize !== undefined && typeof buidlerNetwork.allowUnlimitedContractSize !== "boolean") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.allowUnlimitedContractSize`, buidlerNetwork.allowUnlimitedContractSize, "boolean | undefined")); } if (buidlerNetwork.initialDate !== undefined && typeof buidlerNetwork.initialDate !== "string") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.initialDate`, buidlerNetwork.initialDate, "string | undefined")); } if (buidlerNetwork.throwOnTransactionFailures !== undefined && typeof buidlerNetwork.throwOnTransactionFailures !== "boolean") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.throwOnTransactionFailures`, buidlerNetwork.throwOnTransactionFailures, "boolean | undefined")); } if (buidlerNetwork.throwOnCallFailures !== undefined && typeof buidlerNetwork.throwOnCallFailures !== "boolean") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.throwOnCallFailures`, buidlerNetwork.throwOnCallFailures, "boolean | undefined")); } if (buidlerNetwork.url !== undefined) { errors.push(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME} can't have an url`); } if (buidlerNetwork.blockGasLimit !== undefined && typeof buidlerNetwork.blockGasLimit !== "number") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.blockGasLimit`, buidlerNetwork.blockGasLimit, "number | undefined")); } if (buidlerNetwork.chainId !== undefined && typeof buidlerNetwork.chainId !== "number") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.chainId`, buidlerNetwork.chainId, "number | undefined")); } if (buidlerNetwork.loggingEnabled !== undefined && typeof buidlerNetwork.loggingEnabled !== "boolean") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.loggingEnabled`, buidlerNetwork.loggingEnabled, "boolean | undefined")); } if (buidlerNetwork.accounts !== undefined) { if (Array.isArray(buidlerNetwork.accounts)) { for (const account of buidlerNetwork.accounts) { if (typeof account.privateKey !== "string") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.accounts[].privateKey`, account.privateKey, "string")); } if (typeof account.balance !== "string") { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.accounts[].balance`, account.balance, "string")); } } } else { errors.push(getErrorMessage(`BuidlerConfig.networks.${constants_1.BUIDLEREVM_NETWORK_NAME}.accounts`, buidlerNetwork.accounts, "[{privateKey: string, balance: string}] | undefined")); } } } for (const [networkName, netConfig] of Object.entries(config.networks)) { if (networkName === constants_1.BUIDLEREVM_NETWORK_NAME) { continue; } if (networkName === "localhost" && netConfig.url === undefined) { continue; } if (typeof netConfig.url !== "string") { errors.push(getErrorMessage(`BuidlerConfig.networks.${networkName}.url`, netConfig.url, "string")); } const netConfigResult = HttpNetworkConfig.decode(netConfig); if (netConfigResult.isLeft()) { errors.push(getErrorMessage(`BuidlerConfig.networks.${networkName}`, netConfig, "HttpNetworkConfig")); } } } // io-ts can get confused if there are errors that it can't understand. // Especially around BuidlerEVM's config. It will treat it as an HTTPConfig, // and may give a loot of errors. if (errors.length > 0) { return errors; } const result = BuidlerConfig.decode(config); if (result.isRight()) { return errors; } const ioTsErrors = exports.DotPathReporter.report(result); return [...errors, ...ioTsErrors]; } exports.getValidationErrors = getValidationErrors; //# sourceMappingURL=config-validation.js.map