Skip to content

Commit

Permalink
🎁 Add hardhat-utils package (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista authored Nov 10, 2023
1 parent 71dea02 commit a42fbe0
Show file tree
Hide file tree
Showing 19 changed files with 1,263 additions and 153 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/publish-packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:

concurrency: ${{ github.workflow }}-${{ github.ref }}

env:
NPM_TOKEN: ""

jobs:
publish:
name: Publish
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/vape-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
NPM_TOKEN: ""

jobs:
build-and-test:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions packages/hardhat-utils/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
1 change: 1 addition & 0 deletions packages/hardhat-utils/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cache
2 changes: 2 additions & 0 deletions packages/hardhat-utils/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
node_modules/
29 changes: 29 additions & 0 deletions packages/hardhat-utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<p align="center">
<a href="https://layerzero.network">
<img alt="LayerZero" style="max-width: 500px" src="https://d3a2dpnnrypp5h.cloudfront.net/bridge-app/lz.png"/>
</a>
</p>

<h1 align="center">@layerzerolabs/hardhat-utils</h1>

<!-- The badges section -->
<p align="center">
<!-- Shields.io NPM published package version -->
<a href="https://www.npmjs.com/package/@layerzerolabs/hardhat-utils"><img alt="NPM Version" src="https://img.shields.io/npm/v/@layerzerolabs/hardhat-utils"/></a>
<!-- Shields.io NPM downloads -->
<a href="https://www.npmjs.com/package/@layerzerolabs/hardhat-utils"><img alt="Downloads" src="https://img.shields.io/npm/dm/@layerzerolabs/hardhat-utils"/></a>
<!-- Shields.io vulnerabilities -->
<a href="https://www.npmjs.com/package/@layerzerolabs/hardhat-utils"><img alt="Snyk Vulnerabilities for npm package version" src="https://img.shields.io/snyk/vulnerabilities/npm/@layerzerolabs/hardhat-utils"/></a>
<!-- Shields.io license badge -->
<a href="https://www.npmjs.com/package/@layerzerolabs/hardhat-utils"><img alt="NPM License" src="https://img.shields.io/npm/l/@layerzerolabs/hardhat-utils"/></a>
</p>

## Installation

```bash
yarn add @layerzerolabs/hardhat-utils

pnpm add @layerzerolabs/hardhat-utils

npm install @layerzerolabs/hardhat-utils
```
21 changes: 21 additions & 0 deletions packages/hardhat-utils/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HardhatUserConfig } from "hardhat/types"

/**
* This is a dummy hardhat config that enables us to test
* hardhat functionality without mocking too much
*/
const config: HardhatUserConfig = {
networks: {
"ethereum-mainnet": {
url: "https://eth.llamarpc.com",
},
"bsc-testnet": {
url: "https://bsc-testnet.publicnode.com",
accounts: {
mnemonic: "test test test test test test test test test test test junk",
},
},
},
}

export default config
56 changes: 56 additions & 0 deletions packages/hardhat-utils/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@layerzerolabs/hardhat-utils",
"description": "Hardhat helpers for LayerZero EVM projects",
"version": "0.0.1",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
"exports": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"files": [
"./dist/index.*"
],
"scripts": {
"build": "npx tsup",
"clean": "rm -rf dist",
"dev": "npx tsup --watch",
"lint": "npx eslint '**/*.{js,ts,json}'",
"prebuild": "npx tsc --noEmit -p tsconfig.build.json",
"test": "npx hardhat test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/LayerZero-Labs/lz-utils.git",
"directory": "packages/hardhat-utils"
},
"devDependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@ethersproject/wallet": "^5.7.0",
"@layerzerolabs/lz-definitions": "~1.5.58",
"@types/chai-as-promised": "^7.1.7",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"hardhat": "^2.9.9",
"hardhat-deploy": "^0.11.22",
"sinon": "^17.0.1",
"ts-node": "^10.9.1",
"tsup": "~7.2.0",
"typescript": "^5.2.2"
},
"peerDependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@layerzerolabs/lz-definitions": "~1.5.58",
"hardhat": "^2.9.9",
"hardhat-deploy": "^0.9.19"
},
"dependencies": {
"p-memoize": "~4.0.1",
"zod": "^3.22.4"
}
}
126 changes: 126 additions & 0 deletions packages/hardhat-utils/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import "hardhat-deploy/dist/src/type-extensions"

import { chainAndStageToNetwork, networkToStage, Chain, Stage } from "@layerzerolabs/lz-definitions"
import { HardhatUserConfig, HttpNetworkAccountsUserConfig, NetworksConfig } from "hardhat/types"
import { join } from "path"

export const getMnemonic = (networkName: string): string | undefined =>
process.env[`MNEMONIC_${networkName}`] ||
process.env[`MNEMONIC_${networkName.toUpperCase()}`] ||
process.env[`MNEMONIC_${networkName.toUpperCase().replace(/-/g, "_")}`] ||
process.env.MNEMONIC

export const getAccounts = (networkName: string): HttpNetworkAccountsUserConfig => {
const mnemonic = getMnemonic(networkName)
if (mnemonic == null) return []

return { mnemonic }
}

/**
* Adds external deployments directories for all configured networks.
*
* This function takes the root `deploymentsDir` path to the deployments folder
* and maps all configured networks to point to the network directories under this root path.
*
* ```typescript
* const config = {
* networks: {
* "slipknot-testnet": {}
* }
* }
*
* const configWithExternals = withExternalDeployments("./path/to/some/deployments/folder")(config);
*
* // The configWithExternals will now look like this:
*
* {
* external: {
* deployments: {
* "slipknot-testnet": ["./path/to/some/deployments/folder/slipknot-testnet"]
* }
* },
* networks: {
* "slipknot-testnet": {}
* }
* }
* ```
*
* @param deploymentsDir Path to the external deployments directory
*
* @returns `HardhatUserConfig`
*/
export const withExternalDeployments =
(deploymentsDir: string) =>
<THardhatUserConfig extends HardhatUserConfig>(config: THardhatUserConfig): THardhatUserConfig => ({
...config,
external: {
...config.external,
deployments: Object.fromEntries(
// Map the configured networks into entries for the external deployments object
Object.keys(config.networks ?? {}).map((networkName: string) => {
return [
// The external deployments object is keyed by network names
networkName,
// And its values are arrays of filesystem paths referring to individual network deployment directories
Array.from(
// Since we want the paths to be unique, we'll put everything we have into a Set, then convert back to array
new Set(
// These are the external deployments already configured
config.external?.deployments?.[networkName] ?? []
).add(
// And we're going to add a new one by concatenating the root deployments directory with the network name
join(deploymentsDir, networkName)
)
),
]
})
),
},
})

/**
* Helper utility that takes in an array of Chain identifiers
* and maps them to network names.
*
* If there are no chains defined, the defaults are supplied from the network config
*
* @param config `NetworksConfig`
* @param stage `Stage`
*
* @returns `(chains: Chain[] | null | undefined) => string[]`
*/
export const createGetDefinedNetworkNamesOnStage =
(config: NetworksConfig) =>
(stage: Stage, chains: Chain[] | null | undefined): string[] => {
const definedNetworks = Object.keys(config).sort()
const definedNetworksSet = new Set(definedNetworks)

return (
chains
// We map the chains (e.g. bsc, avalanche) to network names (e.g. bsc-testnet)
?.map((chain: Chain) => chainAndStageToNetwork(chain, stage))
// Filter out networks that have not been defined in the config
// (since we just created them with the correct stage, we don't need to filter by stage)
.filter((networkName) => definedNetworksSet.has(networkName)) ??
// But if we nothing has been provided, we take all the networks from hardhat config
definedNetworks
// And filter out the networks for this stage (since we know all of thse have been defined)
.filter(isNetworkOnStage(stage))
)
}

/**
* Helper utility that safely calls networkToStage
* to determine whether a network name is on stage
*
* @param stage `Stage`
* @returns `true` if network is a valid network name and is on stage, `false` otherwise
*/
const isNetworkOnStage = (stage: Stage) => (networkName: string) => {
try {
return networkToStage(networkName) === stage
} catch {
return false
}
}
3 changes: 3 additions & 0 deletions packages/hardhat-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./config"
export * from "./runtime"
export * from "./types"
Loading

0 comments on commit a42fbe0

Please sign in to comment.