@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
JavaScript
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
;