Skip to content

Commit

Permalink
chore: Add a hardhat task for exporting deployments
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista committed Feb 15, 2024
1 parent 1fda35c commit 6532108
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/devtools-evm-hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"test": "jest --ci --forceExit"
},
"dependencies": {
"@layerzerolabs/export-deployments": "~0.0.1",
"micro-memoize": "~4.1.2",
"p-memoize": "~4.0.4",
"zod": "^3.22.4"
Expand Down
2 changes: 2 additions & 0 deletions packages/devtools-evm-hardhat/src/constants/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const TASK_LZ_DEPLOY = 'lz:deploy'

export const TASK_LZ_EXPORT_DEPLOYMENTS_TYPESCRIPT = 'lz:export:deployments:typescript'

export const SUBTASK_LZ_SIGN_AND_SEND = '::lz:sign-and-send'
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { task } from 'hardhat/config'
import type { ActionType } from 'hardhat/types'
import { TASK_LZ_EXPORT_DEPLOYMENTS_TYPESCRIPT } from '@/constants/tasks'
import { OutputFile, createIncludeDirent, generate, generatorTypeScript } from '@layerzerolabs/export-deployments'
import { createLogger, pluralizeNoun, printBoolean, setDefaultLogLevel } from '@layerzerolabs/io-devtools'

import { printLogo } from '@layerzerolabs/io-devtools/swag'
import { types } from '@/cli'

interface TaskArgs {
contracts?: string[]
networks?: string[]
outDir?: string
logLevel?: string
}

const action: ActionType<TaskArgs> = async (
{ networks, contracts, logLevel = 'info', outDir = 'generated' },
hre
): Promise<OutputFile[]> => {
printLogo()

// We'll set the global logging level to get as much info as needed
setDefaultLogLevel(logLevel)

// And we'll create a logger for ourselves
const logger = createLogger()

// We just go ahead and export, not a care in the world
const results = generate({
// Since we are in a hardhat project, the deployments path is coming from the config
deploymentsDir: hre.config.paths.deployments,
outDir,
includeDeploymentFile: createIncludeDirent(contracts),
includeNetworkDir: createIncludeDirent(networks),
generator: generatorTypeScript,
})

logger.info(
`${printBoolean(true)} ${pluralizeNoun(results.length, `Generated 1 file:`, `Generated ${results.length} files`)}`
)

for (const { path } of results) {
logger.info(`\t${path}`)
}

return results
}

task(TASK_LZ_EXPORT_DEPLOYMENTS_TYPESCRIPT, 'Export deployments as TypeScript files', action)
.addParam(
'networks',
'List of comma-separated networks. If not provided, all networks will be deployed',
undefined,
types.csv,
true
)
.addParam(
'contracts',
'List of comma-separated contract names. If not provided, all contracts will be exported',
undefined,
types.csv,
true
)
.addParam('logLevel', 'Logging level. One of: error, warn, info, verbose, debug, silly', 'info', types.logLevel)
1 change: 1 addition & 0 deletions packages/devtools-evm-hardhat/src/tasks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './deploy'
export * from './transactions'
export * from './export.deployments.typescript'
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions tests/devtools-evm-hardhat-test/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,13 @@ expect.extend(jestExtended);
// clear all deployments before & after every test
const clearDeployments = () => rmSync('./deployments', { force: true, recursive: true });

beforeEach(clearDeployments);
afterEach(clearDeployments);
// clear all generated files before & after every test
const clearGenerated = () => rmSync('./generated', { force: true, recursive: true });

const clean = () => {
clearDeployments();
clearGenerated();
};

beforeEach(clean);
afterEach(clean);
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Mon Feb 12 16:57:18 2024
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}


set timeout 60

# We deploy contracts
spawn npx hardhat lz:deploy --ci
expect eof

# And export the deployments
spawn npx hardhat lz:export:deployments:typescript
expect "Generated 7 files"
expect eof
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Mon Feb 12 16:57:18 2024
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}


set timeout 60

# We deploy contracts
spawn npx hardhat lz:deploy --ci
expect eof

# And export the deployments
spawn npx hardhat lz:export:deployments:typescript --contracts Thrower
expect "Generated 3 files"
expect eof
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Mon Feb 12 16:57:18 2024
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}


set timeout 60

# We try exporting without the deployments directory (should fail)
spawn npx hardhat lz:export:deployments:typescript
expect -re "Error: Deployments path '.*?' is not a directory. Does it exist?"
expect eof
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Mon Feb 12 16:57:18 2024
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}


set timeout 60

# We deploy contracts
spawn npx hardhat lz:deploy --ci
expect eof

# And export the deployments
spawn npx hardhat lz:export:deployments:typescript --networks tango
expect "Generated 7 files"
expect eof
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/// <reference types="jest-extended" />

import { TASK_LZ_DEPLOY } from '@layerzerolabs/devtools-evm-hardhat'
import { spawnSync } from 'child_process'
import { join } from 'path'

describe(`task ${TASK_LZ_DEPLOY}`, () => {
describe('expectations', () => {
const EXPECTATIONS_DIRECTORY = join('test', 'task', 'export.deployments.typescript.expectations')
const expectationPath = (name: string) => join(EXPECTATIONS_DIRECTORY, `${name}.exp`)
const runExpect = (name: string) =>
spawnSync(expectationPath(name), {
encoding: 'utf8',
stdio: 'inherit',
})

const ALL_NETWORKS = ['britney', 'tango', 'vengaboys']
const ALL_DEPLOYMENTS = [
'DefaultProxyAdmin',
'TestProxy',
'TestProxy_Implementation',
'TestProxy_Proxy',
'Thrower',
]

it('should export all deployments', async () => {
const result = runExpect('export-all')

expect(result.status).toBe(0)

expect(require('../../generated').names).toContainAllValues(ALL_DEPLOYMENTS)
expect(require('../../generated/TestProxy').abis).toContainAllKeys(ALL_NETWORKS)
expect(require('../../generated/Thrower').abis).toContainAllKeys(ALL_NETWORKS)
})

it('should export a single contract on all networks', async () => {
const result = runExpect('export-contract')

expect(result.status).toBe(0)

expect(require('../../generated').names).toEqual(['Thrower'])
expect(require('../../generated/Thrower').abis).toContainAllKeys(ALL_NETWORKS)
})

it('should error out without deployments folder', async () => {
const result = runExpect('export-missing-deployments')

expect(result.status).toBe(0)
})

it('should export a single network', async () => {
const result = runExpect('export-network')

expect(result.status).toBe(0)

expect(require('../../generated').names).toContainAllValues(ALL_DEPLOYMENTS)
expect(require('../../generated/TestProxy').abis).toContainAllKeys(['tango'])
expect(require('../../generated/Thrower').abis).toContainAllKeys(['tango'])
})
})
})

0 comments on commit 6532108

Please sign in to comment.