hardhat 2.18.3 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builtin-tasks/vars.d.ts +2 -0
- package/builtin-tasks/vars.d.ts.map +1 -0
- package/builtin-tasks/vars.js +41 -0
- package/builtin-tasks/vars.js.map +1 -0
- package/internal/cli/cli.js +4 -0
- package/internal/cli/cli.js.map +1 -1
- package/internal/cli/vars.d.ts +2 -0
- package/internal/cli/vars.d.ts.map +1 -0
- package/internal/cli/vars.js +216 -0
- package/internal/cli/vars.js.map +1 -0
- package/internal/context.d.ts +4 -0
- package/internal/context.d.ts.map +1 -1
- package/internal/context.js +3 -0
- package/internal/context.js.map +1 -1
- package/internal/core/config/config-env.d.ts +34 -0
- package/internal/core/config/config-env.d.ts.map +1 -1
- package/internal/core/config/config-env.js +47 -1
- package/internal/core/config/config-env.js.map +1 -1
- package/internal/core/config/config-loading.d.ts +1 -0
- package/internal/core/config/config-loading.d.ts.map +1 -1
- package/internal/core/config/config-loading.js +2 -1
- package/internal/core/config/config-loading.js.map +1 -1
- package/internal/core/errors-list.d.ts +30 -0
- package/internal/core/errors-list.d.ts.map +1 -1
- package/internal/core/errors-list.js +36 -1
- package/internal/core/errors-list.js.map +1 -1
- package/internal/core/tasks/builtin-tasks.d.ts +1 -0
- package/internal/core/tasks/builtin-tasks.d.ts.map +1 -1
- package/internal/core/tasks/builtin-tasks.js +1 -0
- package/internal/core/tasks/builtin-tasks.js.map +1 -1
- package/internal/core/vars/vars-manager-setup.d.ts +22 -0
- package/internal/core/vars/vars-manager-setup.d.ts.map +1 -0
- package/internal/core/vars/vars-manager-setup.js +95 -0
- package/internal/core/vars/vars-manager-setup.js.map +1 -0
- package/internal/core/vars/vars-manager.d.ts +21 -0
- package/internal/core/vars/vars-manager.d.ts.map +1 -0
- package/internal/core/vars/vars-manager.js +110 -0
- package/internal/core/vars/vars-manager.js.map +1 -0
- package/internal/hardhat-network/stack-traces/constants.d.ts +1 -1
- package/internal/hardhat-network/stack-traces/constants.js +1 -1
- package/internal/solidity/compiler/solc-info.d.ts.map +1 -1
- package/internal/solidity/compiler/solc-info.js +1 -0
- package/internal/solidity/compiler/solc-info.js.map +1 -1
- package/internal/util/global-dir.d.ts +1 -0
- package/internal/util/global-dir.d.ts.map +1 -1
- package/internal/util/global-dir.js +5 -1
- package/internal/util/global-dir.js.map +1 -1
- package/package.json +1 -1
- package/src/builtin-tasks/vars.ts +54 -0
- package/src/internal/cli/cli.ts +5 -1
- package/src/internal/cli/vars.ts +301 -0
- package/src/internal/context.ts +8 -0
- package/src/internal/core/config/config-env.ts +54 -0
- package/src/internal/core/config/config-loading.ts +1 -1
- package/src/internal/core/errors-list.ts +39 -1
- package/src/internal/core/tasks/builtin-tasks.ts +1 -0
- package/src/internal/core/vars/vars-manager-setup.ts +124 -0
- package/src/internal/core/vars/vars-manager.ts +152 -0
- package/src/internal/hardhat-network/stack-traces/constants.ts +1 -1
- package/src/internal/solidity/compiler/solc-info.ts +1 -0
- package/src/internal/util/global-dir.ts +4 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { HardhatError } from "../internal/core/errors";
|
|
2
|
+
import { scope } from "../internal/core/config/config-env";
|
|
3
|
+
import { ERRORS } from "../internal/core/errors-list";
|
|
4
|
+
|
|
5
|
+
const varsScope = scope("vars", "Manage your configuration variables");
|
|
6
|
+
|
|
7
|
+
varsScope
|
|
8
|
+
.task("set", "Set the value of a configuration variable")
|
|
9
|
+
.addPositionalParam("var", "The name of the variable")
|
|
10
|
+
.addOptionalPositionalParam(
|
|
11
|
+
"value",
|
|
12
|
+
"The value to store. Omit to be prompted for it."
|
|
13
|
+
)
|
|
14
|
+
.setAction(async () => {
|
|
15
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
varsScope
|
|
19
|
+
.task("get", "Get the value of a configuration variable")
|
|
20
|
+
.addPositionalParam("var", "The name of the variable")
|
|
21
|
+
.setAction(async () => {
|
|
22
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
varsScope
|
|
26
|
+
.task("list", "List all the configuration variables")
|
|
27
|
+
.setAction(async () => {
|
|
28
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
varsScope
|
|
32
|
+
.task("delete", "Delete a configuration variable")
|
|
33
|
+
.addPositionalParam("var", "The name of the variable")
|
|
34
|
+
.setAction(async () => {
|
|
35
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
varsScope
|
|
39
|
+
.task(
|
|
40
|
+
"path",
|
|
41
|
+
"Show the path of the file where all the configuration variables are stored"
|
|
42
|
+
)
|
|
43
|
+
.setAction(async () => {
|
|
44
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
varsScope
|
|
48
|
+
.task(
|
|
49
|
+
"setup",
|
|
50
|
+
"Show how to setup the configuration variables used by this project"
|
|
51
|
+
)
|
|
52
|
+
.setAction(async () => {
|
|
53
|
+
throw new HardhatError(ERRORS.VARS.ONLY_MANAGED_IN_CLI);
|
|
54
|
+
});
|
package/src/internal/cli/cli.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import debug from "debug";
|
|
3
3
|
import "source-map-support/register";
|
|
4
|
-
|
|
5
4
|
import {
|
|
6
5
|
TASK_COMPILE,
|
|
7
6
|
TASK_HELP,
|
|
@@ -50,6 +49,7 @@ import {
|
|
|
50
49
|
installHardhatVSCode,
|
|
51
50
|
isHardhatVSCodeInstalled,
|
|
52
51
|
} from "./hardhat-vscode-installation";
|
|
52
|
+
import { handleVars } from "./vars";
|
|
53
53
|
|
|
54
54
|
const log = debug("hardhat:core:cli");
|
|
55
55
|
|
|
@@ -212,6 +212,10 @@ async function main() {
|
|
|
212
212
|
|
|
213
213
|
const ctx = HardhatContext.createHardhatContext();
|
|
214
214
|
|
|
215
|
+
if (scopeOrTaskName === "vars" && allUnparsedCLAs.length > 1) {
|
|
216
|
+
process.exit(await handleVars(allUnparsedCLAs, hardhatArguments.config));
|
|
217
|
+
}
|
|
218
|
+
|
|
215
219
|
const { resolvedConfig, userConfig } = loadConfigAndTasks(
|
|
216
220
|
hardhatArguments,
|
|
217
221
|
{
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import debug from "debug";
|
|
3
|
+
import { HardhatError, assertHardhatInvariant } from "../core/errors";
|
|
4
|
+
import { ERRORS } from "../core/errors-list";
|
|
5
|
+
import { HardhatContext } from "../context";
|
|
6
|
+
import { VarsManagerSetup } from "../core/vars/vars-manager-setup";
|
|
7
|
+
import {
|
|
8
|
+
importCsjOrEsModule,
|
|
9
|
+
resolveConfigPath,
|
|
10
|
+
} from "../core/config/config-loading";
|
|
11
|
+
import { getVarsFilePath } from "../util/global-dir";
|
|
12
|
+
import { ArgumentsParser } from "./ArgumentsParser";
|
|
13
|
+
import { emoji } from "./emoji";
|
|
14
|
+
|
|
15
|
+
const log = debug("hardhat:cli:vars");
|
|
16
|
+
|
|
17
|
+
export async function handleVars(
|
|
18
|
+
allUnparsedCLAs: string[],
|
|
19
|
+
configPath: string | undefined
|
|
20
|
+
): Promise<number> {
|
|
21
|
+
const { taskDefinition, taskArguments } =
|
|
22
|
+
await getTaskDefinitionAndTaskArguments(allUnparsedCLAs);
|
|
23
|
+
|
|
24
|
+
switch (taskDefinition.name) {
|
|
25
|
+
case "set":
|
|
26
|
+
return set(taskArguments.var, taskArguments.value);
|
|
27
|
+
case "get":
|
|
28
|
+
return get(taskArguments.var);
|
|
29
|
+
case "list":
|
|
30
|
+
return list();
|
|
31
|
+
case "delete":
|
|
32
|
+
return del(taskArguments.var);
|
|
33
|
+
case "path":
|
|
34
|
+
return path();
|
|
35
|
+
case "setup":
|
|
36
|
+
return setup(configPath);
|
|
37
|
+
default:
|
|
38
|
+
console.error(chalk.red(`Invalid task '${taskDefinition.name}'`));
|
|
39
|
+
return 1; // Error code
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function set(key: string, value?: string): Promise<number> {
|
|
44
|
+
const varsManager = HardhatContext.getHardhatContext().varsManager;
|
|
45
|
+
|
|
46
|
+
varsManager.validateKey(key);
|
|
47
|
+
|
|
48
|
+
varsManager.set(key, value ?? (await getVarValue()));
|
|
49
|
+
|
|
50
|
+
if (process.stdout.isTTY) {
|
|
51
|
+
console.warn(
|
|
52
|
+
`The configuration variable has been stored in ${varsManager.getStoragePath()}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function get(key: string): number {
|
|
60
|
+
const value = HardhatContext.getHardhatContext().varsManager.get(key);
|
|
61
|
+
|
|
62
|
+
if (value !== undefined) {
|
|
63
|
+
console.log(value);
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.warn(
|
|
68
|
+
chalk.yellow(
|
|
69
|
+
`The configuration variable '${key}' is not set in ${HardhatContext.getHardhatContext().varsManager.getStoragePath()}`
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function list(): number {
|
|
76
|
+
const keys = HardhatContext.getHardhatContext().varsManager.list();
|
|
77
|
+
const varsStoragePath =
|
|
78
|
+
HardhatContext.getHardhatContext().varsManager.getStoragePath();
|
|
79
|
+
|
|
80
|
+
if (keys.length > 0) {
|
|
81
|
+
keys.forEach((k) => console.log(k));
|
|
82
|
+
|
|
83
|
+
if (process.stdout.isTTY) {
|
|
84
|
+
console.warn(
|
|
85
|
+
`\nAll configuration variables are stored in ${varsStoragePath}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
if (process.stdout.isTTY) {
|
|
90
|
+
console.warn(
|
|
91
|
+
chalk.yellow(
|
|
92
|
+
`There are no configuration variables stored in ${varsStoragePath}`
|
|
93
|
+
)
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function del(key: string): number {
|
|
102
|
+
const varsStoragePath =
|
|
103
|
+
HardhatContext.getHardhatContext().varsManager.getStoragePath();
|
|
104
|
+
|
|
105
|
+
if (HardhatContext.getHardhatContext().varsManager.delete(key)) {
|
|
106
|
+
if (process.stdout.isTTY) {
|
|
107
|
+
console.warn(
|
|
108
|
+
`The configuration variable was deleted from ${varsStoragePath}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.warn(
|
|
115
|
+
chalk.yellow(
|
|
116
|
+
`There is no configuration variable '${key}' to delete from ${varsStoragePath}`
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function path() {
|
|
124
|
+
console.log(HardhatContext.getHardhatContext().varsManager.getStoragePath());
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function setup(configPath: string | undefined) {
|
|
129
|
+
log("Switching to SetupVarsManager to collect vars");
|
|
130
|
+
|
|
131
|
+
const varsManagerSetup = new VarsManagerSetup(getVarsFilePath());
|
|
132
|
+
|
|
133
|
+
HardhatContext.getHardhatContext().varsManager = varsManagerSetup;
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
log("Loading config and tasks to trigger vars collection");
|
|
137
|
+
loadConfigFile(configPath);
|
|
138
|
+
} catch (err: any) {
|
|
139
|
+
console.error(
|
|
140
|
+
chalk.red(
|
|
141
|
+
"There is an error in your Hardhat configuration file. Please double check it.\n"
|
|
142
|
+
)
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
listVarsToSetup(varsManagerSetup);
|
|
150
|
+
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The code below duplicates a section from the 'loadConfigAndTasks' function.
|
|
155
|
+
// While we could have refactored the 'config-loading.ts' module to make this logic reusable,
|
|
156
|
+
// it would have added complexity and potentially made the code harder to understand.
|
|
157
|
+
function loadConfigFile(configPath: string | undefined) {
|
|
158
|
+
const configEnv = require(`../core/config/config-env`);
|
|
159
|
+
|
|
160
|
+
// Load all the functions and objects exported by the 'config-env' file in a global scope
|
|
161
|
+
const globalAsAny: any = global;
|
|
162
|
+
Object.entries(configEnv).forEach(
|
|
163
|
+
([key, value]) => (globalAsAny[key] = value)
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const resolvedConfigPath = resolveConfigPath(configPath);
|
|
167
|
+
importCsjOrEsModule(resolvedConfigPath);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function getVarValue(): Promise<string> {
|
|
171
|
+
const { default: enquirer } = await import("enquirer");
|
|
172
|
+
|
|
173
|
+
const response: { value: string } = await enquirer.prompt({
|
|
174
|
+
type: "password",
|
|
175
|
+
name: "value",
|
|
176
|
+
message: "Enter value:",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return response.value;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function listVarsToSetup(varsManagerSetup: VarsManagerSetup) {
|
|
183
|
+
const HH_SET_COMMAND = "npx hardhat vars set";
|
|
184
|
+
|
|
185
|
+
const requiredKeysToSet = varsManagerSetup.getRequiredVarsToSet();
|
|
186
|
+
const optionalKeysToSet = varsManagerSetup.getOptionalVarsToSet();
|
|
187
|
+
|
|
188
|
+
if (requiredKeysToSet.length === 0 && optionalKeysToSet.length === 0) {
|
|
189
|
+
console.log(
|
|
190
|
+
chalk.green(
|
|
191
|
+
"There are no configuration variables that need to be set for this project"
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
console.log();
|
|
195
|
+
printAlreadySetKeys(varsManagerSetup);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (requiredKeysToSet.length > 0) {
|
|
200
|
+
console.log(
|
|
201
|
+
chalk.bold(
|
|
202
|
+
`${emoji("❗ ")}The following configuration variables need to be set:\n`
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
console.log(
|
|
206
|
+
requiredKeysToSet.map((k) => ` ${HH_SET_COMMAND} ${k}`).join("\n")
|
|
207
|
+
);
|
|
208
|
+
console.log();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (optionalKeysToSet.length > 0) {
|
|
212
|
+
console.log(
|
|
213
|
+
chalk.bold(
|
|
214
|
+
`${emoji("💡 ")}The following configuration variables are optional:\n`
|
|
215
|
+
)
|
|
216
|
+
);
|
|
217
|
+
console.log(
|
|
218
|
+
optionalKeysToSet.map((k) => ` ${HH_SET_COMMAND} ${k}`).join("\n")
|
|
219
|
+
);
|
|
220
|
+
console.log();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
printAlreadySetKeys(varsManagerSetup);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function printAlreadySetKeys(varsManagerSetup: VarsManagerSetup) {
|
|
227
|
+
const requiredKeysAlreadySet = varsManagerSetup.getRequiredVarsAlreadySet();
|
|
228
|
+
const optionalKeysAlreadySet = varsManagerSetup.getOptionalVarsAlreadySet();
|
|
229
|
+
const envVars = varsManagerSetup.getEnvVars();
|
|
230
|
+
|
|
231
|
+
if (
|
|
232
|
+
requiredKeysAlreadySet.length === 0 &&
|
|
233
|
+
optionalKeysAlreadySet.length === 0 &&
|
|
234
|
+
envVars.length === 0
|
|
235
|
+
) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
console.log(
|
|
240
|
+
`${chalk.bold(`${emoji("✔️ ")}Configuration variables already set:`)}`
|
|
241
|
+
);
|
|
242
|
+
console.log();
|
|
243
|
+
|
|
244
|
+
if (requiredKeysAlreadySet.length > 0) {
|
|
245
|
+
console.log(" Mandatory:");
|
|
246
|
+
console.log(requiredKeysAlreadySet.map((x) => ` ${x}`).join("\n"));
|
|
247
|
+
console.log();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (optionalKeysAlreadySet.length > 0) {
|
|
251
|
+
console.log(" Optional:");
|
|
252
|
+
console.log(optionalKeysAlreadySet.map((x) => ` ${x}`).join("\n"));
|
|
253
|
+
console.log();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (envVars.length > 0) {
|
|
257
|
+
console.log(" Set via environment variables:");
|
|
258
|
+
console.log(envVars.map((x) => ` ${x}`).join("\n"));
|
|
259
|
+
console.log();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function getTaskDefinitionAndTaskArguments(allUnparsedCLAs: string[]) {
|
|
264
|
+
const ctx = HardhatContext.getHardhatContext();
|
|
265
|
+
ctx.setConfigLoadingAsStarted();
|
|
266
|
+
require("../../builtin-tasks/vars");
|
|
267
|
+
ctx.setConfigLoadingAsFinished();
|
|
268
|
+
|
|
269
|
+
const argumentsParser = new ArgumentsParser();
|
|
270
|
+
|
|
271
|
+
const taskDefinitions = ctx.tasksDSL.getTaskDefinitions();
|
|
272
|
+
const scopesDefinitions = ctx.tasksDSL.getScopesDefinitions();
|
|
273
|
+
|
|
274
|
+
const { scopeName, taskName, unparsedCLAs } =
|
|
275
|
+
argumentsParser.parseScopeAndTaskNames(
|
|
276
|
+
allUnparsedCLAs,
|
|
277
|
+
taskDefinitions,
|
|
278
|
+
scopesDefinitions
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
assertHardhatInvariant(
|
|
282
|
+
scopeName === "vars",
|
|
283
|
+
"This function should only be called to handle tasks under the 'vars' scope"
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const taskDefinition = ctx.tasksDSL.getTaskDefinition(scopeName, taskName);
|
|
287
|
+
|
|
288
|
+
if (taskDefinition === undefined) {
|
|
289
|
+
throw new HardhatError(ERRORS.ARGUMENTS.UNRECOGNIZED_SCOPED_TASK, {
|
|
290
|
+
scope: scopeName,
|
|
291
|
+
task: taskName,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const taskArguments = argumentsParser.parseTaskArguments(
|
|
296
|
+
taskDefinition,
|
|
297
|
+
unparsedCLAs
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
return { taskDefinition, taskArguments };
|
|
301
|
+
}
|
package/src/internal/context.ts
CHANGED
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import { assertHardhatInvariant, HardhatError } from "./core/errors";
|
|
10
10
|
import { ERRORS } from "./core/errors-list";
|
|
11
|
+
import { VarsManagerSetup } from "./core/vars/vars-manager-setup";
|
|
12
|
+
import { VarsManager } from "./core/vars/vars-manager";
|
|
11
13
|
import { TasksDSL } from "./core/tasks/dsl";
|
|
14
|
+
import { getVarsFilePath } from "./util/global-dir";
|
|
12
15
|
import { getRequireCachedFiles } from "./util/platform";
|
|
13
16
|
|
|
14
17
|
export type GlobalWithHardhatContext = typeof global & {
|
|
@@ -16,6 +19,10 @@ export type GlobalWithHardhatContext = typeof global & {
|
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
export class HardhatContext {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.varsManager = new VarsManager(getVarsFilePath());
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
public static isCreated(): boolean {
|
|
20
27
|
const globalWithHardhatContext = global as GlobalWithHardhatContext;
|
|
21
28
|
return globalWithHardhatContext.__hardhatContext !== undefined;
|
|
@@ -49,6 +56,7 @@ export class HardhatContext {
|
|
|
49
56
|
public readonly environmentExtenders: EnvironmentExtender[] = [];
|
|
50
57
|
public environment?: HardhatRuntimeEnvironment;
|
|
51
58
|
public readonly providerExtenders: ProviderExtender[] = [];
|
|
59
|
+
public varsManager: VarsManager | VarsManagerSetup;
|
|
52
60
|
|
|
53
61
|
public readonly configExtenders: ConfigExtender[] = [];
|
|
54
62
|
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
TaskArguments,
|
|
10
10
|
} from "../../../types";
|
|
11
11
|
import { HardhatContext } from "../../context";
|
|
12
|
+
import { HardhatError } from "../errors";
|
|
13
|
+
import { ERRORS } from "../errors-list";
|
|
12
14
|
import * as argumentTypes from "../params/argumentTypes";
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -173,3 +175,55 @@ export function experimentalAddHardhatNetworkMessageTraceHook(
|
|
|
173
175
|
const ctx = HardhatContext.getHardhatContext();
|
|
174
176
|
ctx.experimentalHardhatNetworkMessageTraceHooks.push(hook);
|
|
175
177
|
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* This object provides methods to interact with the configuration variables.
|
|
181
|
+
*/
|
|
182
|
+
export const vars = {
|
|
183
|
+
has: hasVar,
|
|
184
|
+
get: getVar,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Checks if a configuration variable exists.
|
|
189
|
+
*
|
|
190
|
+
* @remarks
|
|
191
|
+
* This method, when used during setup (via `npx hardhat vars setup`), will mark the variable as optional.
|
|
192
|
+
*
|
|
193
|
+
* @param varName - The name of the variable to check.
|
|
194
|
+
*
|
|
195
|
+
* @returns `true` if the variable exists, `false` otherwise.
|
|
196
|
+
*/
|
|
197
|
+
function hasVar(varName: string): boolean {
|
|
198
|
+
// varsManager will be an instance of VarsManager or VarsManagerSetup depending on the context (vars setup mode or not)
|
|
199
|
+
return HardhatContext.getHardhatContext().varsManager.has(varName, true);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Gets the value of the given configuration variable.
|
|
204
|
+
*
|
|
205
|
+
* @remarks
|
|
206
|
+
* This method, when used during setup (via `npx hardhat vars setup`), will mark the variable as required,
|
|
207
|
+
* unless a default value is provided.
|
|
208
|
+
*
|
|
209
|
+
* @param varName - The name of the variable to retrieve.
|
|
210
|
+
* @param [defaultValue] - An optional default value to return if the variable does not exist.
|
|
211
|
+
*
|
|
212
|
+
* @returns The value of the configuration variable if it exists, or the default value if provided.
|
|
213
|
+
*
|
|
214
|
+
* @throws HH1201 if the variable does not exist and no default value is set.
|
|
215
|
+
*/
|
|
216
|
+
function getVar(varName: string, defaultValue?: string): string {
|
|
217
|
+
// varsManager will be an instance of VarsManager or VarsManagerSetup depending on the context (vars setup mode or not)
|
|
218
|
+
const value = HardhatContext.getHardhatContext().varsManager.get(
|
|
219
|
+
varName,
|
|
220
|
+
defaultValue,
|
|
221
|
+
true
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
if (value !== undefined) return value;
|
|
225
|
+
|
|
226
|
+
throw new HardhatError(ERRORS.VARS.VALUE_NOT_FOUND_FOR_VAR, {
|
|
227
|
+
value: varName,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
@@ -25,7 +25,7 @@ import { DEFAULT_SOLC_VERSION } from "./default-config";
|
|
|
25
25
|
|
|
26
26
|
const log = debug("hardhat:core:config");
|
|
27
27
|
|
|
28
|
-
function importCsjOrEsModule(filePath: string): any {
|
|
28
|
+
export function importCsjOrEsModule(filePath: string): any {
|
|
29
29
|
try {
|
|
30
30
|
const imported = require(filePath);
|
|
31
31
|
return imported.default !== undefined ? imported.default : imported;
|
|
@@ -41,6 +41,7 @@ export const ERROR_RANGES: {
|
|
|
41
41
|
INTERNAL: { min: 900, max: 999, title: "Internal Hardhat errors" },
|
|
42
42
|
SOURCE_NAMES: { min: 1000, max: 1099, title: "Source name errors" },
|
|
43
43
|
CONTRACT_NAMES: { min: 1100, max: 1199, title: "Contract name errors" },
|
|
44
|
+
VARS: { min: 1200, max: 1299, title: "Connfiguration variables errors" },
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
export const ERRORS = {
|
|
@@ -643,7 +644,7 @@ Please double check your task definitions.`,
|
|
|
643
644
|
ARGUMENTS: {
|
|
644
645
|
INVALID_ENV_VAR_VALUE: {
|
|
645
646
|
number: 300,
|
|
646
|
-
message: "Invalid environment variable %varName%'
|
|
647
|
+
message: "Invalid environment variable '%varName%' with value: '%value%'",
|
|
647
648
|
title: "Invalid environment variable value",
|
|
648
649
|
description: `You are setting one of Hardhat's arguments using an environment variable, but it has an incorrect value.
|
|
649
650
|
|
|
@@ -1298,6 +1299,43 @@ A fully qualified name should look like file.sol:Contract`,
|
|
|
1298
1299
|
shouldBeReported: false,
|
|
1299
1300
|
},
|
|
1300
1301
|
},
|
|
1302
|
+
VARS: {
|
|
1303
|
+
ONLY_MANAGED_IN_CLI: {
|
|
1304
|
+
number: 1200,
|
|
1305
|
+
title: "Configuration variables can only be managed from the CLI",
|
|
1306
|
+
message:
|
|
1307
|
+
"Configuration variables can only be managed from the CLI. They cannot be modified programmatically.",
|
|
1308
|
+
description: `Configuration variables can only be managed from the CLI. They cannot be modified programmatically.`,
|
|
1309
|
+
shouldBeReported: false,
|
|
1310
|
+
},
|
|
1311
|
+
VALUE_NOT_FOUND_FOR_VAR: {
|
|
1312
|
+
number: 1201,
|
|
1313
|
+
title: "Configuration variable is not set",
|
|
1314
|
+
message:
|
|
1315
|
+
"Cannot find a value for the configuration variable '%value%'. Use 'npx hardhat vars set %value%' to set it or 'npx hardhat vars setup' to list all the configuration variables used by this project.",
|
|
1316
|
+
description: `Cannot find a value for a mandatory configuration variable.
|
|
1317
|
+
|
|
1318
|
+
Use 'npx hardhat vars set VAR' to set it or 'npx hardhat vars setup' to list all the configuration variables used by this project.`,
|
|
1319
|
+
shouldBeReported: false,
|
|
1320
|
+
},
|
|
1321
|
+
INVALID_CONFIG_VAR_NAME: {
|
|
1322
|
+
number: 1202,
|
|
1323
|
+
title: "Invalid name for a configuration variable",
|
|
1324
|
+
message:
|
|
1325
|
+
"Invalid name for a configuration variable: '%value%'. Configuration variables can only have alphanumeric characters and underscores, and they cannot start with a number.",
|
|
1326
|
+
description: `Invalid name for a configuration variable.
|
|
1327
|
+
|
|
1328
|
+
Configuration variables can only have alphanumeric characters and underscores, and they cannot start with a number.`,
|
|
1329
|
+
shouldBeReported: false,
|
|
1330
|
+
},
|
|
1331
|
+
INVALID_EMPTY_VALUE: {
|
|
1332
|
+
number: 1203,
|
|
1333
|
+
title: "Invalid empty value for configuration variable",
|
|
1334
|
+
message: "A configuration variable cannot have an empty value.",
|
|
1335
|
+
description: "A configuration variable cannot have an empty value.",
|
|
1336
|
+
shouldBeReported: false,
|
|
1337
|
+
},
|
|
1338
|
+
},
|
|
1301
1339
|
};
|
|
1302
1340
|
|
|
1303
1341
|
/**
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
import { VarsManager } from "./vars-manager";
|
|
3
|
+
|
|
4
|
+
const log = debug("hardhat:core:vars:varsManagerSetup");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This class is ONLY used when collecting the required and optional vars that have to be filled by the user
|
|
8
|
+
*/
|
|
9
|
+
export class VarsManagerSetup extends VarsManager {
|
|
10
|
+
private readonly _getVarsAlreadySet: Set<string>;
|
|
11
|
+
private readonly _hasVarsAlreadySet: Set<string>;
|
|
12
|
+
private readonly _getVarsWithDefaultValueAlreadySet: Set<string>;
|
|
13
|
+
|
|
14
|
+
private readonly _getVarsToSet: Set<string>;
|
|
15
|
+
private readonly _hasVarsToSet: Set<string>;
|
|
16
|
+
private readonly _getVarsWithDefaultValueToSet: Set<string>;
|
|
17
|
+
|
|
18
|
+
constructor(varsFilePath: string) {
|
|
19
|
+
log("Creating a new instance of VarsManagerSetup");
|
|
20
|
+
|
|
21
|
+
super(varsFilePath);
|
|
22
|
+
|
|
23
|
+
this._getVarsAlreadySet = new Set();
|
|
24
|
+
this._hasVarsAlreadySet = new Set();
|
|
25
|
+
this._getVarsWithDefaultValueAlreadySet = new Set();
|
|
26
|
+
|
|
27
|
+
this._getVarsToSet = new Set();
|
|
28
|
+
this._hasVarsToSet = new Set();
|
|
29
|
+
this._getVarsWithDefaultValueToSet = new Set();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Checks if the key exists, and updates sets accordingly.
|
|
33
|
+
// Ignore the parameter 'includeEnvs' defined in the parent class because during setup env vars are ignored.
|
|
34
|
+
public has(key: string): boolean {
|
|
35
|
+
log(`function 'has' called with key '${key}'`);
|
|
36
|
+
|
|
37
|
+
const hasKey = super.has(key);
|
|
38
|
+
|
|
39
|
+
if (hasKey) {
|
|
40
|
+
this._hasVarsAlreadySet.add(key);
|
|
41
|
+
} else {
|
|
42
|
+
this._hasVarsToSet.add(key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return hasKey;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Gets the value for the provided key, and updates sets accordingly.
|
|
49
|
+
// Ignore the parameter 'includeEnvs' defined in the parent class because during setup env vars are ignored.
|
|
50
|
+
public get(key: string, defaultValue?: string): string {
|
|
51
|
+
log(`function 'get' called with key '${key}'`);
|
|
52
|
+
|
|
53
|
+
const varAlreadySet = super.has(key);
|
|
54
|
+
|
|
55
|
+
if (varAlreadySet) {
|
|
56
|
+
if (defaultValue !== undefined) {
|
|
57
|
+
this._getVarsWithDefaultValueAlreadySet.add(key);
|
|
58
|
+
} else {
|
|
59
|
+
this._getVarsAlreadySet.add(key);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
if (defaultValue !== undefined) {
|
|
63
|
+
this._getVarsWithDefaultValueToSet.add(key);
|
|
64
|
+
} else {
|
|
65
|
+
this._getVarsToSet.add(key);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Do not return undefined to avoid throwing an error
|
|
70
|
+
return super.get(key, defaultValue) ?? "";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public getRequiredVarsAlreadySet(): string[] {
|
|
74
|
+
return this._getRequired(this._getVarsAlreadySet, this._hasVarsAlreadySet);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public getOptionalVarsAlreadySet(): string[] {
|
|
78
|
+
return this._getOptionals(
|
|
79
|
+
this._getVarsAlreadySet,
|
|
80
|
+
this._hasVarsAlreadySet,
|
|
81
|
+
this._getVarsWithDefaultValueAlreadySet
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public getRequiredVarsToSet(): string[] {
|
|
86
|
+
return this._getRequired(this._getVarsToSet, this._hasVarsToSet);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public getOptionalVarsToSet(): string[] {
|
|
90
|
+
return this._getOptionals(
|
|
91
|
+
this._getVarsToSet,
|
|
92
|
+
this._hasVarsToSet,
|
|
93
|
+
this._getVarsWithDefaultValueToSet
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// How to calculate required and optional variables:
|
|
98
|
+
//
|
|
99
|
+
// G = get function
|
|
100
|
+
// H = has function
|
|
101
|
+
// GD = get function with default value
|
|
102
|
+
//
|
|
103
|
+
// optional variables = H + (GD - G)
|
|
104
|
+
// required variables = G - H
|
|
105
|
+
private _getRequired(getVars: Set<string>, hasVars: Set<string>): string[] {
|
|
106
|
+
return Array.from(getVars).filter((k) => !hasVars.has(k));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private _getOptionals(
|
|
110
|
+
getVars: Set<string>,
|
|
111
|
+
hasVars: Set<string>,
|
|
112
|
+
getVarsWithDefault: Set<string>
|
|
113
|
+
): string[] {
|
|
114
|
+
const result = new Set(hasVars);
|
|
115
|
+
|
|
116
|
+
for (const k of getVarsWithDefault) {
|
|
117
|
+
if (!getVars.has(k)) {
|
|
118
|
+
result.add(k);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return Array.from(result);
|
|
123
|
+
}
|
|
124
|
+
}
|