Skip to content

Commit

Permalink
chore: Add collectDeployments utility to utils-evm-hardhat
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista committed Nov 28, 2023
1 parent 4c54913 commit 69d82b4
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 9 deletions.
4 changes: 4 additions & 0 deletions packages/utils-evm-hardhat/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const config: HardhatUserConfig = {
saveDeployments: true,
endpointId: EndpointId.ETHEREUM_MAINNET,
},
'ethereum-testnet': {
url: 'https://eth-goerli.public.blastapi.io',
endpointId: EndpointId.ETHEREUM_TESTNET,
},
'bsc-testnet': {
url: 'https://bsc-testnet.publicnode.com',
accounts: {
Expand Down
1 change: 1 addition & 0 deletions packages/utils-evm-hardhat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import './type-extensions'
// Regular exports
export * from './config'
export * from './logger'
export * from './omnigraph'
export * from './provider'
export * from './runtime'
export * from './types'
39 changes: 39 additions & 0 deletions packages/utils-evm-hardhat/src/omnigraph/coordinates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { Deployment } from 'hardhat-deploy/dist/types'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import { assertHardhatDeploy } from '../internal/assertions'
import { getNetworkNamesByEid, getNetworkRuntimeEnvironment } from '../runtime'

export interface OmniDeployment {
eid: EndpointId
deployment: Deployment
}

/**
* Collects all deployment of a certain contract along with their endpoint IDs.
*
* Network s which don't have `endpointId` configured in their hardhat network config will be ignored
*
* @param hre `HardhatRuntimeEnvironment`
* @param contractName `string`
* @returns `OmniDeployment[]`
*/
export const collectDeployments = async (
hre: HardhatRuntimeEnvironment,
contractName: string
): Promise<OmniDeployment[]> => {
assertHardhatDeploy(hre)

const deployments: OmniDeployment[] = []
const networkNamesByEid = getNetworkNamesByEid(hre)

for (const [eid, networkName] of networkNamesByEid) {
const env = await getNetworkRuntimeEnvironment(networkName)
const deployment = await env.deployments.getOrNull(contractName)
if (deployment == null) continue

deployments.push({ eid, deployment })
}

return deployments
}
1 change: 1 addition & 0 deletions packages/utils-evm-hardhat/src/omnigraph/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './coordinates'
33 changes: 24 additions & 9 deletions packages/utils-evm-hardhat/src/runtime.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { HardhatRuntimeEnvironment, EIP1193Provider } from 'hardhat/types'
import type { HardhatRuntimeEnvironment, EIP1193Provider, Network } from 'hardhat/types'

import pMemoize from 'p-memoize'
import { Web3Provider } from '@ethersproject/providers'
Expand Down Expand Up @@ -100,14 +100,7 @@ export const wrapEIP1193Provider = (provider: EIP1193Provider): Web3Provider =>
export const createNetworkEnvironmentFactory = (
hre: HardhatRuntimeEnvironment
): EndpointBasedFactory<HardhatRuntimeEnvironment> => {
const networks = Object.entries(hre.config.networks)
const networkNamesByEndpointId: Map<EndpointId, string> = new Map(
networks.flatMap(([networkName, { endpointId }]) => {
if (endpointId == null) return []

return [[endpointId, networkName]]
})
)
const networkNamesByEndpointId = getNetworkNamesByEid(hre)

return async (eid) => {
const networkName = networkNamesByEndpointId.get(eid)
Expand All @@ -116,3 +109,25 @@ export const createNetworkEnvironmentFactory = (
return getNetworkRuntimeEnvironment(networkName)
}
}

/**
* Creates a mapping between EndpointId and network name
* based on the hardhat project configuration.
*
* It will silently ignore networks that don't have `endpointId`
* specified in their network configuration.
*
* @param hre `HardhatRuntimeEnvironment`
* @returns `Map<EndpointId, string>`
*/
export const getNetworkNamesByEid = (hre: HardhatRuntimeEnvironment): Map<EndpointId, string> => {
const networks = Object.entries(hre.config.networks)

return new Map(
networks.flatMap(([networkName, networkConfig]) => {
if (networkConfig.endpointId == null) return []

return [[networkConfig.endpointId, networkName]]
})
)
}
118 changes: 118 additions & 0 deletions packages/utils-evm-hardhat/test/omnigraph/coordinates.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { collectDeployments } from '../../src/omnigraph'
import { expect } from 'chai'
import { describe } from 'mocha'
import hre from 'hardhat'
import { DeploymentSubmission } from 'hardhat-deploy/dist/types'
import { getNetworkRuntimeEnvironment } from '../../src/runtime'

describe('omnigraph/coordinates', () => {
beforeEach(async () => {
const bscTestnetRuntime = await getNetworkRuntimeEnvironment('bsc-testnet')
const ethMainnetRuntime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
const ethTestnetRuntime = await getNetworkRuntimeEnvironment('ethereum-testnet')

await bscTestnetRuntime.deployments.delete('MyWeirdContract')
await ethMainnetRuntime.deployments.delete('MyWeirdContract')
await ethTestnetRuntime.deployments.delete('MyWeirdContract')
})

describe('collectDeployments', () => {
it('should return an empty array if there are no deployments', async () => {
const deployments = await collectDeployments(hre, 'NonExistentContract')

expect(deployments).to.eql([])
})

it('should skip a network if endpointId is missing', async () => {
// First we make sure that the network we want to deploy to has no endpointId
const bscRuntime = await getNetworkRuntimeEnvironment('bsc-testnet')
expect(bscRuntime.network.config.endpointId).to.be.undefined

// Now we create a mock deployment
const now = Date.now()
const deploymentSubmission = {
args: [now],
} as DeploymentSubmission

// Save it
await bscRuntime.deployments.save('MyWeirdContract', deploymentSubmission)

// And check that it will not be picked up
const deployments = await collectDeployments(hre, 'MyWeirdContract')

expect(deployments).to.eql([])
})

it('should skip a network if deployment is missing', async () => {
// First we make sure that the network we want to deploy to has an endpointId
const ethRuntime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
expect(ethRuntime.network.config.endpointId).not.to.be.undefined

// Now we create a mock deployment
const now = Date.now()
const deploymentSubmission = {
args: [now],
} as DeploymentSubmission

// Save it
await ethRuntime.deployments.save('MyWeirdContract', deploymentSubmission)

// And check that it will not be picked up
const deployments = await collectDeployments(hre, 'MyWeirdContract')

// Now check that bsc-testnet and ethereum-testnet did not get included
expect(deployments).to.eql([
{
eid: ethRuntime.network.config.endpointId,
deployment: {
...deploymentSubmission,
numDeployments: 1,
},
},
])
})

it('should include all deployments that have endpointId configured', async () => {
// First we make sure that the networks we want to deploy to have endpointId
const ethMainnetRuntime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
const ethTestnetRuntime = await getNetworkRuntimeEnvironment('ethereum-testnet')
expect(ethMainnetRuntime.network.config.endpointId).not.to.be.undefined
expect(ethTestnetRuntime.network.config.endpointId).not.to.be.undefined

// Now we create mock deployments
const now = Date.now()
const deploymentSubmissionMainnet = {
args: ['mainnet', now],
} as DeploymentSubmission

const deploymentSubmissionTestnet = {
args: ['testnet', now],
} as DeploymentSubmission

// Save it
await ethMainnetRuntime.deployments.save('MyWeirdContract', deploymentSubmissionMainnet)
await ethTestnetRuntime.deployments.save('MyWeirdContract', deploymentSubmissionTestnet)

// And check that it will not be picked up
const deployments = await collectDeployments(hre, 'MyWeirdContract')

// Now check that bsc-testnet and ethereum-testnet did not get included
expect(deployments).to.eql([
{
eid: ethMainnetRuntime.network.config.endpointId,
deployment: {
...deploymentSubmissionMainnet,
numDeployments: 1,
},
},
{
eid: ethTestnetRuntime.network.config.endpointId,
deployment: {
...deploymentSubmissionTestnet,
numDeployments: 1,
},
},
])
})
})
})

0 comments on commit 69d82b4

Please sign in to comment.