This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Devise new package @truffle/from-hardhat
... for compatibility translation
- Loading branch information
Showing
13 changed files
with
939 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": ["../../.eslintrc.package.json"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
dist | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# @truffle/from-hardhat | ||
|
||
> :warning: **This package is experimental and FOR INTERNAL USE ONLY.** | ||
This package translates Hardhat project information into Truffle's own formats. | ||
|
||
For information on using this package (until we get it more ready for public | ||
use), please see [`./src/api.ts`](src/api.ts). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "@truffle/from-hardhat", | ||
"description": "Import Hardhat project information into Truffle-native formats", | ||
"license": "MIT", | ||
"author": "g. nicholas d'andrea <gnidan@trufflesuite.com>", | ||
"homepage": "https://github.com/trufflesuite/truffle/tree/master/packages/from-hardhat#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/trufflesuite/truffle.git", | ||
"directory": "packages/from-hardhat" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/trufflesuite/truffle/issues" | ||
}, | ||
"version": "0.1.0-0", | ||
"main": "dist/src/index.js", | ||
"scripts": { | ||
"build": "ttsc", | ||
"prepare": "yarn build", | ||
"test": "exit 0" | ||
}, | ||
"dependencies": { | ||
"@truffle/compile-common": "^0.7.32", | ||
"@truffle/compile-solidity": "^6.0.38", | ||
"@truffle/config": "^1.3.34", | ||
"debug": "^4.3.1", | ||
"find-up": "^2.1.0", | ||
"semver": "^5.7.1" | ||
}, | ||
"devDependencies": { | ||
"@types/find-up": "^2.1.0", | ||
"@types/node": "^18.6.5", | ||
"hardhat": "^2.10.1", | ||
"ttypescript": "1.5.13", | ||
"typescript": "^4.3.5", | ||
"typescript-transform-paths": "3.3.1" | ||
}, | ||
"keywords": [ | ||
"ethereum", | ||
"solidity", | ||
"truffle", | ||
"hardhat" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { promises as fs } from "fs"; | ||
import semver from "semver"; | ||
|
||
import type * as Hardhat from "hardhat/types"; | ||
import type * as Common from "@truffle/compile-common"; | ||
import type TruffleConfig from "@truffle/config"; | ||
|
||
import { supportedHardhatVersionRange } from "./constants"; | ||
import * as Compilation from "./compilation"; | ||
import * as Config from "./config"; | ||
|
||
import { | ||
checkHardhat, | ||
askHardhatConsole, | ||
askHardhatVersion | ||
} from "./ask-hardhat"; | ||
import { EnvironmentOptions } from "./options"; | ||
|
||
/** | ||
* Checks for the existence of a Hardhat project configuration and asserts | ||
* that the local installed version of Hardhat matches this package's | ||
* supported version range. | ||
* | ||
* @param options to control process environment (e.g. working directory) | ||
* @return Promise<void> when expectation holds | ||
* @throws NotHardhatError when not in a Hardhat project directory | ||
* @throws IncompatibleHardhatError if Hardhat has unsupported version | ||
*/ | ||
export const expectHardhat = async ( | ||
options?: EnvironmentOptions | ||
): Promise<void> => { | ||
const isHardhat = await checkHardhat(options); | ||
|
||
if (!isHardhat) { | ||
throw new NotHardhatError(); | ||
} | ||
|
||
const hardhatVersion = await askHardhatVersion(options); | ||
|
||
if (!semver.satisfies(hardhatVersion, supportedHardhatVersionRange)) { | ||
throw new IncompatibleHardhatError(hardhatVersion); | ||
} | ||
}; | ||
|
||
/** | ||
* Thrown when no Hardhat project is found | ||
*/ | ||
export class NotHardhatError extends Error { | ||
constructor() { | ||
super("Current working directory is not part of a Hardhat project"); | ||
} | ||
} | ||
|
||
/** | ||
* Thrown when Hardhat was detected but with an incompatible version | ||
*/ | ||
export class IncompatibleHardhatError extends Error { | ||
constructor(detectedVersion: string) { | ||
super( | ||
`Expected Hardhat version compatible with ${supportedHardhatVersionRange}, got: ${detectedVersion}` | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Constructs a @truffle/config object based on the Hardhat config. | ||
* | ||
* WARNING: except for fields documented here, the values present on the | ||
* returned @truffle/config object MUST be regarded as unsafe to use. | ||
* | ||
* The returned `config` is defined to contain the following: | ||
* | ||
* - `config.networks` with configurations for all Hardhat-configured | ||
* networks, provided: | ||
* - The configured network is not the built-in `hardhat` network | ||
* - The configured network defines a `url` property | ||
* | ||
* Note: this function ignores all properties other than `url`, | ||
* including any information that can be used for computing | ||
* cryptographic signatures. THIS FUNCTION DOES NOT READ PRIVATE KEYS. | ||
* | ||
* Suffice to say: | ||
* | ||
* THIS FUNCTION'S BEHAVIOR IS EXPERIMENTAL AND SHOULD ONLY BE USED IN | ||
* SPECIFICALLY KNOWN-SUPPORTED USE CASES (like reading for configured | ||
* network urls) | ||
* | ||
* @param options to control process environment (e.g. working directory) | ||
* @return Promise<TruffleConfig> with the following fields: | ||
* | ||
* @dev This function shells out to `npx hardhat console` to ask the Hardhat | ||
* runtime environment for a fully populated config object. | ||
*/ | ||
export const prepareConfig = async ( | ||
options?: EnvironmentOptions | ||
): Promise<TruffleConfig> => { | ||
const hardhatConfig = (await askHardhatConsole( | ||
`hre.config`, | ||
options | ||
)) as Hardhat.HardhatConfig; | ||
|
||
return Config.fromHardhatConfig(hardhatConfig); | ||
}; | ||
|
||
/** | ||
* Constructs an array of @truffle/compile-common `Compilation` objects | ||
* corresponding one-to-one with Hardhat's persisted results of each solc | ||
* compilation. | ||
* | ||
* WARNING: this function only supports Hardhat projects written entirely | ||
* in solc-compatible languages (Solidity, Yul). Behavior of this function | ||
* for Hardhat projects using other languages is undefined. | ||
* | ||
* @param options to control process environment (e.g. working directory) | ||
* @return Promise<Compilation[]> from @truffle/compile-common | ||
* | ||
* @dev This function shells out to `npx hardhat console` to ask the Hardhat | ||
* runtime environment for the location of the project build info | ||
* files | ||
*/ | ||
export const prepareCompilations = async ( | ||
options?: EnvironmentOptions | ||
): Promise<Common.Compilation[]> => { | ||
const compilations = []; | ||
|
||
const buildInfoPaths = (await askHardhatConsole( | ||
`artifacts.getBuildInfoPaths()`, | ||
options | ||
)) as string[]; | ||
|
||
for (const buildInfoPath of buildInfoPaths) { | ||
const buildInfo: Hardhat.BuildInfo = JSON.parse( | ||
(await fs.readFile(buildInfoPath)).toString() | ||
); | ||
|
||
const compilation = Compilation.fromBuildInfo(buildInfo); | ||
|
||
compilations.push(compilation); | ||
} | ||
|
||
return compilations; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { spawn } from "child_process"; | ||
|
||
import findUp from "find-up"; | ||
|
||
import { validHardhatConfigFilenames } from "./constants"; | ||
import { EnvironmentOptions, withDefaultEnvironmentOptions } from "./options"; | ||
|
||
/** | ||
* Returns a Promise to a boolean that is true if and only if | ||
* the detected or specified environment is part of a Hardhat project. | ||
* | ||
* (i.e., if the working directory or any of its parents has a Hardhat config) | ||
*/ | ||
export const checkHardhat = async ( | ||
options?: EnvironmentOptions | ||
): Promise<boolean> => { | ||
const { workingDirectory } = withDefaultEnvironmentOptions(options); | ||
|
||
// search recursively up for a hardhat config | ||
const hardhatConfigPath = await findUp(validHardhatConfigFilenames, { | ||
cwd: workingDirectory | ||
}); | ||
|
||
return !!hardhatConfigPath; | ||
}; | ||
|
||
/** | ||
* Reads version information via `npx hardhat --version` | ||
*/ | ||
export const askHardhatVersion = async ( | ||
options?: EnvironmentOptions | ||
): Promise<string> => | ||
new Promise((accept, reject) => { | ||
const { workingDirectory } = withDefaultEnvironmentOptions(options); | ||
|
||
const hardhat = spawn(`npx`, ["hardhat", "--version"], { | ||
stdio: "pipe", | ||
cwd: workingDirectory | ||
}); | ||
|
||
let output = ""; | ||
hardhat.stdout.on("data", data => { | ||
output = `${output}${data}`; | ||
}); | ||
|
||
// setup close event before writing to stdin because we're sending eof | ||
hardhat.on("close", code => { | ||
if (code !== 0) { | ||
return reject(new Error(`Hardhat exited with non-zero code ${code}`)); | ||
} | ||
|
||
return accept(output); | ||
}); | ||
}); | ||
|
||
export interface AskHardhatConsoleOptions { | ||
// turn off json stringify/parse | ||
raw?: boolean; | ||
} | ||
|
||
export const askHardhatConsole = async ( | ||
expression: string, | ||
{ | ||
raw = false, | ||
...options | ||
}: AskHardhatConsoleOptions & EnvironmentOptions = {} | ||
): Promise<string | unknown> => | ||
new Promise((accept, reject) => { | ||
const { workingDirectory } = withDefaultEnvironmentOptions(options); | ||
|
||
const hardhat = spawn(`npx`, ["hardhat", "console"], { | ||
stdio: ["pipe", "pipe", "inherit"], | ||
cwd: workingDirectory | ||
}); | ||
|
||
// we'll capture the stdout | ||
let output = ""; | ||
hardhat.stdout.on("data", data => { | ||
output = `${output}${data}`; | ||
}); | ||
|
||
// setup close event before writing to stdin because we're sending eof | ||
hardhat.on("close", code => { | ||
if (code !== 0) { | ||
return reject(new Error(`Hardhat exited with non-zero code ${code}`)); | ||
} | ||
|
||
if (raw) { | ||
return accept(output); | ||
} | ||
|
||
try { | ||
return accept(JSON.parse(output)); | ||
} catch (error) { | ||
return reject(error); | ||
} | ||
}); | ||
|
||
hardhat.stdin.write(` | ||
Promise.resolve(${expression}) | ||
.then(${ | ||
raw | ||
? `console.log` | ||
: `(resolved) => console.log(JSON.stringify(resolved))` | ||
}) | ||
`); | ||
hardhat.stdin.end(); | ||
}); |
Oops, something went wrong.