-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dce8ff4
commit 1ed8f3f
Showing
15 changed files
with
789 additions
and
13 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
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,99 @@ | ||
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 { arePointsEqual, 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') | ||
|
||
assert(britneyEnv.network.config.endpointId, 'Missing endpointId on britney network') | ||
assert(vengaboysEnv.network.config.endpointId, 'Missing endpointId on vengaboys network') | ||
|
||
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: [], | ||
}) | ||
}) | ||
|
||
it('should collect all newly deployed DefaultOApp contracts', async () => { | ||
const britneyEnv = await getNetworkRuntimeEnvironment('britney') | ||
const vengaboysEnv = await getNetworkRuntimeEnvironment('vengaboys') | ||
|
||
assert(britneyEnv.network.config.endpointId, 'Missing endpointId on britney network') | ||
assert(vengaboysEnv.network.config.endpointId, 'Missing endpointId on vengaboys network') | ||
|
||
const oldBritneyDeployment = await britneyEnv.deployments.get('DefaultOApp') | ||
const oldVengaboysDeployment = await vengaboysEnv.deployments.get('DefaultOApp') | ||
|
||
const oldBritneyPoint: OmniPoint = eidAndDeploymentToPoint( | ||
britneyEnv.network.config.endpointId, | ||
oldBritneyDeployment | ||
) | ||
const oldVengaboysPoint: OmniPoint = eidAndDeploymentToPoint( | ||
vengaboysEnv.network.config.endpointId, | ||
oldVengaboysDeployment | ||
) | ||
|
||
// First we create a builder using the redeployed contracts | ||
const oldBuilder = await OmniGraphBuilderHardhat.fromDeployedContract(hre, 'DefaultOApp') | ||
|
||
// Now we redeploy one of the contracts | ||
const [_, deployer] = await britneyEnv.getUnnamedAccounts() | ||
assert(deployer, 'Missing deployer') | ||
|
||
await britneyEnv.deployments.delete('DefaultOApp') | ||
const newBritneyDeployment = await britneyEnv.deployments.deploy('DefaultOApp', { | ||
from: deployer, | ||
}) | ||
|
||
const newBritneyPoint: OmniPoint = eidAndDeploymentToPoint( | ||
britneyEnv.network.config.endpointId, | ||
newBritneyDeployment | ||
) | ||
|
||
// As a sanity check, we make sure the deployment has actually changed | ||
expect(arePointsEqual(newBritneyPoint, oldBritneyPoint)).to.be.false | ||
|
||
const builder = await OmniGraphBuilderHardhat.fromDeployedContract(hre, 'DefaultOApp') | ||
|
||
expect(oldBuilder.graph).not.to.eql(builder.graph) | ||
expect(builder.graph).to.eql({ | ||
contracts: [ | ||
{ | ||
point: oldVengaboysPoint, | ||
config: undefined, | ||
}, | ||
{ | ||
point: newBritneyPoint, | ||
config: undefined, | ||
}, | ||
], | ||
connections: [], | ||
}) | ||
}) | ||
}) |
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
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 @@ | ||
export * from './omnigraph' |
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,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`) |
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,33 @@ | ||
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' | ||
|
||
export class OmniGraphBuilderHardhat<TNodeConfig, TEdgeConfig> extends OmniGraphBuilder<TNodeConfig, TEdgeConfig> { | ||
static async fromDeployedContract( | ||
hre: HardhatRuntimeEnvironment, | ||
contractName: string | ||
): Promise<OmniGraphBuilder<undefined, undefined>> { | ||
const builder = new OmniGraphBuilder<undefined, undefined>() | ||
|
||
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 | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/ua-utils-evm-hardhat/src/omnigraph/coordinates.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,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<OmniPoint | undefined> => { | ||
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, | ||
}) |
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 @@ | ||
export * from './builder' | ||
export * from './coordinates' |
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 |
---|---|---|
@@ -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'], | ||
}, | ||
]) |
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
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 assert from 'assert' | ||
import { arePointsEqual, serializePoint, serializeVector } from './coordinates' | ||
import type { OmniEdge, OmniGraph, OmniNode, OmniPoint, OmniVector } from './types' | ||
|
||
export class OmniGraphBuilder<TNodeConfig, TEdgeConfig> { | ||
#nodes: Map<string, OmniNode<TNodeConfig>> = new Map() | ||
|
||
#edges: Map<string, OmniEdge<TEdgeConfig>> = new Map() | ||
|
||
#assertCanAddEdge(edge: OmniEdge<TEdgeConfig>): void { | ||
const label = serializeVector(edge.vector) | ||
const from = serializePoint(edge.vector.from) | ||
|
||
assert(this.getNodeAt(edge.vector.from), `Cannot add edge '${label}': '${from}' is not in the graph`) | ||
} | ||
|
||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
// | ||
// The builder methods | ||
// | ||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
|
||
addNodes(...nodes: OmniNode<TNodeConfig>[]): this { | ||
return nodes.forEach((node) => this.#nodes.set(serializePoint(node.point), node)), this | ||
} | ||
|
||
addEdges(...edges: OmniEdge<TEdgeConfig>[]): this { | ||
return ( | ||
edges.forEach((edge) => { | ||
// First we make sure we can add this edge | ||
this.#assertCanAddEdge(edge) | ||
|
||
// Only then we add it | ||
this.#edges.set(serializeVector(edge.vector), edge) | ||
}), | ||
this | ||
) | ||
} | ||
|
||
removeNodeAt(point: OmniPoint): this { | ||
return ( | ||
// First we remove all edges between this node and any other nodes | ||
[...this.getEdgesFrom(point)].forEach((edge) => this.removeEdgeAt(edge.vector)), | ||
// Only then we remove the node itself | ||
this.#nodes.delete(serializePoint(point)), | ||
this | ||
) | ||
} | ||
|
||
removeEdgeAt(vector: OmniVector): this { | ||
return this.#edges.delete(serializeVector(vector)), this | ||
} | ||
|
||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
// | ||
// The accessor methods | ||
// | ||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
|
||
getNodeAt(point: OmniPoint): OmniNode<TNodeConfig> | undefined { | ||
return this.#nodes.get(serializePoint(point)) | ||
} | ||
|
||
getEdgeAt(vector: OmniVector): OmniEdge<TEdgeConfig> | undefined { | ||
return this.#edges.get(serializeVector(vector)) | ||
} | ||
|
||
getEdgesFrom(point: OmniPoint): OmniEdge<TEdgeConfig>[] { | ||
return this.edges.filter(({ vector: { from } }) => arePointsEqual(point, from)) | ||
} | ||
|
||
getEdgesTo(point: OmniPoint): OmniEdge<TEdgeConfig>[] { | ||
return this.edges.filter(({ vector: { to } }) => arePointsEqual(point, to)) | ||
} | ||
|
||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
// | ||
// The config accessors | ||
// | ||
// .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- | ||
// / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ | ||
// `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' | ||
|
||
get nodes(): OmniNode<TNodeConfig>[] { | ||
return Array.from(this.#nodes.values()) | ||
} | ||
|
||
get edges(): OmniEdge<TEdgeConfig>[] { | ||
return Array.from(this.#edges.values()) | ||
} | ||
|
||
get graph(): OmniGraph<TNodeConfig, TEdgeConfig> { | ||
return { | ||
contracts: this.nodes, | ||
connections: this.edges, | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './builder' | ||
export * from './coordinates' | ||
export * from './schema' | ||
export * from './types' |
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
Oops, something went wrong.