diff --git a/packages/ua-utils-evm-hardhat-test/test/builder.test.ts b/packages/ua-utils-evm-hardhat-test/test/builder.test.ts new file mode 100644 index 000000000..9659c49ae --- /dev/null +++ b/packages/ua-utils-evm-hardhat-test/test/builder.test.ts @@ -0,0 +1,93 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { describe } from 'mocha' +import { eidAndDeploymentToPoint, OmniGraphBuilderHardhat } from '@layerzerolabs/ua-utils-evm-hardhat' +import { getNetworkRuntimeEnvironment } from '@layerzerolabs/utils-evm-hardhat' +import { OmniPoint } from '@layerzerolabs/ua-utils' +import assert from 'assert' + +describe('builder', () => { + it('should collect all deployed DefaultOApp contracts', async () => { + const britneyEnv = await getNetworkRuntimeEnvironment('britney') + const vengaboysEnv = await getNetworkRuntimeEnvironment('vengaboys') + + const britneyDeployment = await britneyEnv.deployments.get('DefaultOApp') + const vengaboysDeployment = await vengaboysEnv.deployments.get('DefaultOApp') + + const britneyPoint: OmniPoint = eidAndDeploymentToPoint(britneyEnv.network.config.endpointId, britneyDeployment) + const vengaboysPoint: OmniPoint = eidAndDeploymentToPoint( + vengaboysEnv.network.config.endpointId, + vengaboysDeployment + ) + + const builder = await OmniGraphBuilderHardhat.fromDeployedContract(hre, 'DefaultOApp') + + expect(builder.graph).to.eql({ + contracts: [ + { + point: vengaboysPoint, + config: undefined, + }, + { + point: britneyPoint, + config: undefined, + }, + ], + connections: [ + { + vector: { from: vengaboysPoint, to: britneyPoint }, + config: undefined, + }, + { + vector: { from: britneyPoint, to: vengaboysPoint }, + config: undefined, + }, + ], + }) + }) + + it('should collect all newly deployed DefaultOApp contracts', async () => { + const britneyEnv = await getNetworkRuntimeEnvironment('britney') + const vengaboysEnv = await getNetworkRuntimeEnvironment('vengaboys') + + const [_, deployer] = await britneyEnv.getUnnamedAccounts() + assert(deployer, 'Missing deployer') + + const britneyDeployment = await britneyEnv.deployments.deploy('DefaultOApp', { + from: deployer, + skipIfAlreadyDeployed: false, + }) + const vengaboysDeployment = await vengaboysEnv.deployments.get('DefaultOApp') + + const britneyPoint: OmniPoint = eidAndDeploymentToPoint(britneyEnv.network.config.endpointId, britneyDeployment) + const vengaboysPoint: OmniPoint = eidAndDeploymentToPoint( + vengaboysEnv.network.config.endpointId, + vengaboysDeployment + ) + + const builder = await OmniGraphBuilderHardhat.fromDeployedContract(hre, 'DefaultOApp') + + expect(builder.graph).to.eql({ + contracts: [ + { + point: vengaboysPoint, + config: undefined, + }, + { + point: britneyPoint, + config: undefined, + }, + ], + connections: [ + { + vector: { from: vengaboysPoint, to: britneyPoint }, + config: undefined, + }, + { + vector: { from: britneyPoint, to: vengaboysPoint }, + config: undefined, + }, + ], + }) + }) +}) diff --git a/packages/ua-utils-evm-hardhat/package.json b/packages/ua-utils-evm-hardhat/package.json index 6bfc18bdf..47ecbc400 100644 --- a/packages/ua-utils-evm-hardhat/package.json +++ b/packages/ua-utils-evm-hardhat/package.json @@ -40,6 +40,8 @@ "@gnosis.pm/safe-ethers-lib": "^1.0.0", "@gnosis.pm/safe-service-client": "1.1.1", "@layerzerolabs/lz-definitions": "~1.5.62", + "@layerzerolabs/ua-utils": "~0.1.0", + "@layerzerolabs/utils-evm-hardhat": "~0.0.2", "@nomiclabs/hardhat-ethers": "^2.2.3", "@types/mocha": "^10.0.6", "cli-ux": "^6.0.9", @@ -48,8 +50,10 @@ "hardhat": "^2.19.0", "hardhat-deploy": "^0.11.22", "ts-node": "^10.9.1", + "tslib": "~2.6.2", "tsup": "^8.0.1", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "zod": "^3.22.4" }, "peerDependencies": { "@gnosis.pm/safe-core-sdk": "^2.0.0", @@ -57,9 +61,12 @@ "@gnosis.pm/safe-ethers-lib": "^1.0.0", "@gnosis.pm/safe-service-client": "1.1.1", "@layerzerolabs/lz-definitions": "~1.5.62", + "@layerzerolabs/ua-utils": "~0.1.0", + "@layerzerolabs/utils-evm-hardhat": "~0.0.2", "@nomiclabs/hardhat-ethers": "^2.2.3", "ethers": "^5.5.2", "hardhat": "^2.19.0", - "hardhat-deploy": "^0.11.22" + "hardhat-deploy": "^0.11.22", + "zod": "^3.22.4" } } \ No newline at end of file diff --git a/packages/ua-utils-evm-hardhat/src/index.ts b/packages/ua-utils-evm-hardhat/src/index.ts new file mode 100644 index 000000000..ac219fd3c --- /dev/null +++ b/packages/ua-utils-evm-hardhat/src/index.ts @@ -0,0 +1 @@ +export * from './omnigraph' diff --git a/packages/ua-utils-evm-hardhat/src/internal/assertions.ts b/packages/ua-utils-evm-hardhat/src/internal/assertions.ts new file mode 100644 index 000000000..2fa885515 --- /dev/null +++ b/packages/ua-utils-evm-hardhat/src/internal/assertions.ts @@ -0,0 +1,6 @@ +import assert from 'assert' +import 'hardhat-deploy/dist/src/type-extensions' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +export const assertHardhatDeploy = (hre: HardhatRuntimeEnvironment) => + assert(hre.deployments, `You don't seem to be using hardhat-deploy in your project`) diff --git a/packages/ua-utils-evm-hardhat/src/omnigraph/builder.ts b/packages/ua-utils-evm-hardhat/src/omnigraph/builder.ts new file mode 100644 index 000000000..77900d500 --- /dev/null +++ b/packages/ua-utils-evm-hardhat/src/omnigraph/builder.ts @@ -0,0 +1,40 @@ +import 'hardhat-deploy/dist/src/type-extensions' +import type { HardhatRuntimeEnvironment } from 'hardhat/types' +import { OmniGraphBuilder } from '@layerzerolabs/ua-utils' +import { createNetworkLogger, getNetworkRuntimeEnvironment } from '@layerzerolabs/utils-evm-hardhat' +import { contractNameToPoint } from './coordinates' +import { vectorFromNodes } from '@layerzerolabs/ua-utils' +import { ignoreLoopback } from '@layerzerolabs/ua-utils' + +export class OmniGraphBuilderHardhat extends OmniGraphBuilder { + static async fromDeployedContract( + hre: HardhatRuntimeEnvironment, + contractName: string + ): Promise> { + const builder = new OmniGraphBuilder() + + for (const networkName of Object.keys(hre.config.networks)) { + const logger = createNetworkLogger(networkName) + const env = await getNetworkRuntimeEnvironment(networkName) + const point = await contractNameToPoint(env, contractName) + + if (point == null) { + logger.warn(`Could not find contract '${contractName}'`) + logger.warn(``) + logger.warn(`- Make sure the contract has been deployed`) + logger.warn(`- Make sure to include the endpointId in your hardhat networks config`) + + continue + } + + builder.addNodes({ point, config: undefined }) + } + + return builder.reconnect( + ignoreLoopback((from, to) => ({ + vector: vectorFromNodes(from, to), + config: undefined, + })) + ) + } +} diff --git a/packages/ua-utils-evm-hardhat/src/omnigraph/coordinates.ts b/packages/ua-utils-evm-hardhat/src/omnigraph/coordinates.ts new file mode 100644 index 000000000..5a5f0e534 --- /dev/null +++ b/packages/ua-utils-evm-hardhat/src/omnigraph/coordinates.ts @@ -0,0 +1,27 @@ +import 'hardhat-deploy/dist/src/type-extensions' +import '@layerzerolabs/utils-evm-hardhat/type-extensions' +import type { EndpointId } from '@layerzerolabs/lz-definitions' +import type { OmniPoint } from '@layerzerolabs/ua-utils' +import type { Deployment } from 'hardhat-deploy/types' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { assertHardhatDeploy } from '@/internal/assertions' + +export const contractNameToPoint = async ( + hre: HardhatRuntimeEnvironment, + contractName: string +): Promise => { + assertHardhatDeploy(hre) + + const eid = hre.network.config.endpointId + if (eid == null) return undefined + + const deployment = await hre.deployments.getOrNull(contractName) + if (deployment == null) return undefined + + return eidAndDeploymentToPoint(eid, deployment) +} + +export const eidAndDeploymentToPoint = (eid: EndpointId, { address }: Deployment): OmniPoint => ({ + eid, + address, +}) diff --git a/packages/ua-utils-evm-hardhat/src/omnigraph/index.ts b/packages/ua-utils-evm-hardhat/src/omnigraph/index.ts new file mode 100644 index 000000000..afcd7e800 --- /dev/null +++ b/packages/ua-utils-evm-hardhat/src/omnigraph/index.ts @@ -0,0 +1,2 @@ +export * from './builder' +export * from './coordinates' diff --git a/packages/ua-utils-evm-hardhat/tsup.config.ts b/packages/ua-utils-evm-hardhat/tsup.config.ts index 6af24d435..c1395151f 100644 --- a/packages/ua-utils-evm-hardhat/tsup.config.ts +++ b/packages/ua-utils-evm-hardhat/tsup.config.ts @@ -1,12 +1,24 @@ import { defineConfig } from 'tsup' -export default defineConfig({ - entry: ['src/tasks/index.ts'], - outDir: './dist/tasks', - clean: true, - dts: true, - sourcemap: true, - splitting: false, - treeshake: true, - format: ['esm', 'cjs'], -}) +export default defineConfig([ + { + entry: ['src/index.ts'], + outDir: './dist', + clean: true, + dts: true, + sourcemap: true, + splitting: false, + treeshake: true, + format: ['esm', 'cjs'], + }, + { + entry: ['src/tasks/index.ts'], + outDir: './dist/tasks', + clean: true, + dts: true, + sourcemap: true, + splitting: false, + treeshake: true, + format: ['esm', 'cjs'], + }, +])