-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add simple config generator based on metadata endpoint (#1115)
- Loading branch information
Showing
21 changed files
with
1,227 additions
and
48 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@layerzerolabs/toolbox-hardhat": patch | ||
"@layerzerolabs/metadata-tools": patch | ||
--- | ||
|
||
add metadata-tools package |
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 @@ | ||
dist | ||
node_modules |
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,3 @@ | ||
{ | ||
"extends": "../../.eslintrc.json" | ||
} |
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 @@ | ||
cache |
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 @@ | ||
dist/ | ||
node_modules/ |
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,38 @@ | ||
<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/metadata-tools</h1> | ||
|
||
<!-- The badges section --> | ||
<p align="center"> | ||
<!-- Shields.io NPM published package version --> | ||
<a href="https://www.npmjs.com/package/@layerzerolabs/metadata-tools"><img alt="NPM Version" src="https://img.shields.io/npm/v/@layerzerolabs/metadata-tools"/></a> | ||
<!-- Shields.io NPM downloads --> | ||
<a href="https://www.npmjs.com/package/@layerzerolabs/metadata-tools"><img alt="Downloads" src="https://img.shields.io/npm/dm/@layerzerolabs/metadata-tools"/></a> | ||
<!-- Shields.io license badge --> | ||
<a href="https://www.npmjs.com/package/@layerzerolabs/metadata-tools"><img alt="NPM License" src="https://img.shields.io/npm/l/@layerzerolabs/metadata-tools"/></a> | ||
</p> | ||
|
||
## Installation | ||
|
||
```bash | ||
yarn add @layerzerolabs/metadata-tools | ||
|
||
pnpm add @layerzerolabs/metadata-tools | ||
|
||
npm install @layerzerolabs/metadata-tools | ||
``` | ||
|
||
## Usage | ||
|
||
```typescript | ||
import { generateConnectionsConfig } from "@layerzerolabs/metadata-tools"; | ||
|
||
// [srcContract, dstContract, [requiredDVNs, [optionalDVNs, threshold]], [srcToDstConfirmations, dstToSrcConfirmations]], [enforcedOptionsSrcToDst, enforcedOptionsDstToSrc] | ||
const connections = await generateConnectionsConfig([ | ||
[avalancheContract, polygonContract, [['LayerZero'], []], [1, 1], [EVM_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS]], | ||
]); | ||
``` |
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,12 @@ | ||
/** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
module.exports = { | ||
cache: false, | ||
reporters: [['github-actions', { silent: false }], 'default'], | ||
testEnvironment: 'node', | ||
moduleNameMapper: { | ||
'^@/(.*)$': '<rootDir>/src/$1', | ||
}, | ||
transform: { | ||
'^.+\\.(t|j)sx?$': '@swc/jest', | ||
}, | ||
}; |
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,56 @@ | ||
{ | ||
"name": "@layerzerolabs/metadata-tools", | ||
"version": "0.0.1", | ||
"description": "LayerZero metadata API tools", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/LayerZero-Labs/devtools.git", | ||
"directory": "packages/metadata-tools" | ||
}, | ||
"license": "MIT", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"require": "./dist/index.js", | ||
"import": "./dist/index.mjs" | ||
}, | ||
"./*": { | ||
"types": "./dist/*.d.ts", | ||
"require": "./dist/*.js", | ||
"import": "./dist/*.mjs" | ||
} | ||
}, | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"prebuild": "$npm_execpath tsc --noEmit", | ||
"build": "$npm_execpath tsup", | ||
"clean": "rm -rf dist", | ||
"dev": "$npm_execpath tsup --watch", | ||
"lint": "$npm_execpath eslint '**/*.{js,ts,json}'", | ||
"lint:fix": "eslint --fix '**/*.{js,ts,json}'", | ||
"test": "jest" | ||
}, | ||
"devDependencies": { | ||
"@layerzerolabs/devtools-evm-hardhat": "~2.0.3", | ||
"@layerzerolabs/ua-devtools": "~3.0.1", | ||
"@swc/core": "^1.4.0", | ||
"@swc/jest": "^0.2.36", | ||
"@types/jest": "^29.5.12", | ||
"jest": "^29.7.0", | ||
"tslib": "~2.6.2", | ||
"tsup": "~8.0.1", | ||
"typescript": "^5.4.4" | ||
}, | ||
"peerDependencies": { | ||
"@layerzerolabs/devtools-evm-hardhat": "~2.0.3", | ||
"@layerzerolabs/ua-devtools": "~3.0.1" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
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,208 @@ | ||
import type { OmniEdgeHardhat } from '@layerzerolabs/devtools-evm-hardhat' | ||
import type { OAppEdgeConfig } from '@layerzerolabs/ua-devtools' | ||
import { IMetadata } from './types' | ||
import { TwoWayConfig } from './types' | ||
|
||
const METADATA_URL = process.env.LZ_METADATA_URL || 'https://metadata.layerzero-api.com/v1/metadata' | ||
|
||
function getEndpointIdDeployment(eid: number, metadata: IMetadata) { | ||
const srcEidString = eid.toString() | ||
for (const objectKey in metadata) { | ||
const entry = metadata[objectKey] | ||
|
||
if (typeof entry?.deployments !== 'undefined') { | ||
for (const deployment of entry.deployments) { | ||
if (srcEidString === deployment.eid) { | ||
return deployment | ||
} | ||
} | ||
} | ||
} | ||
|
||
throw new Error(`Can't find endpoint with eid: "${eid}",`) | ||
} | ||
|
||
export function DVNsToAddresses(dvns: string[], chainKey: string, metadata: IMetadata) { | ||
if (dvns.length === 0) { | ||
return [] | ||
} | ||
|
||
const dvnAddresses: string[] = [] | ||
const seenDVNs = new Set<string>() | ||
|
||
if (!metadata[chainKey]?.dvns) { | ||
throw new Error(`Can't find DVNs for chainKey: "${chainKey}".`) | ||
} | ||
|
||
const metadataDVNs = Object.entries(metadata[chainKey].dvns) | ||
|
||
for (const dvn of dvns) { | ||
if (seenDVNs.has(dvn)) { | ||
throw new Error(`Duplicate DVN name found: "${dvn}".`) | ||
} | ||
seenDVNs.add(dvn) | ||
|
||
let i = 0 | ||
for (const [dvnAddress, dvnDetails] of metadataDVNs) { | ||
if (dvnDetails.canonicalName === dvn && !dvnDetails.lzReadCompatible) { | ||
if (dvnDetails.deprecated) { | ||
console.log(`Warning: DVN "${dvn}" is deprecated.`) | ||
} | ||
|
||
dvnAddresses.push(dvnAddress) | ||
break | ||
} | ||
|
||
if (i === metadataDVNs.length - 1) { | ||
throw new Error( | ||
`Can't find DVN: "${dvn}" on chainKey: "${chainKey}". Double check you're using valid DVN canonical name (not an address).` | ||
) | ||
} | ||
|
||
i++ | ||
} | ||
} | ||
|
||
if (dvns.length !== dvnAddresses.length) { | ||
throw new Error(`Can't find all DVNs: "${dvns.join(', ')}".`) | ||
} | ||
|
||
return dvnAddresses.sort() | ||
} | ||
|
||
export async function translatePathwayToConfig( | ||
pathway: TwoWayConfig, | ||
metadata: IMetadata | ||
): Promise<OmniEdgeHardhat<OAppEdgeConfig | undefined>[]> { | ||
const configs: OmniEdgeHardhat<OAppEdgeConfig | undefined>[] = [] | ||
|
||
const sourceContract = pathway[0] | ||
const destinationContract = pathway[1] | ||
const [requiredDVNs, optionalDVNConfig] = pathway[2] | ||
const [sourceToDestinationConfirmations, destinationToSourceConfirmations] = pathway[3] | ||
const [enforcedOptionsSrcToDst, enforcedOptionsDstToSrc] = pathway[4] | ||
|
||
const optionalDVNs = optionalDVNConfig[0] | ||
const optionalDVNThreshold = optionalDVNConfig[1] || 0 | ||
|
||
if (optionalDVNThreshold > (optionalDVNs?.length || 0)) { | ||
throw new Error(`Optional DVN threshold is greater than the number of optional DVNs.`) | ||
} | ||
|
||
const sourceLZDeployment = getEndpointIdDeployment(sourceContract.eid, metadata) | ||
const destinationLZDeployment = getEndpointIdDeployment(destinationContract.eid, metadata) | ||
|
||
const sourceRequiredDVNs = DVNsToAddresses(requiredDVNs, sourceLZDeployment.chainKey, metadata) | ||
const destinationRequiredDVNs = DVNsToAddresses(requiredDVNs, destinationLZDeployment.chainKey, metadata) | ||
|
||
let sourceOptionalDVNs: string[] = [] | ||
let destinationOptionalDVNs: string[] = [] | ||
|
||
if (optionalDVNs) { | ||
sourceOptionalDVNs = DVNsToAddresses(optionalDVNs, sourceLZDeployment.chainKey, metadata) | ||
destinationOptionalDVNs = DVNsToAddresses(optionalDVNs, destinationLZDeployment.chainKey, metadata) | ||
} | ||
|
||
if (!sourceLZDeployment.sendUln302 || !sourceLZDeployment.receiveUln302 || !sourceLZDeployment.executor) { | ||
throw new Error( | ||
`Can't find sendUln302, receiveUln302 or executor for source endpoint with eid: "${sourceContract.eid}".` | ||
) | ||
} | ||
|
||
if ( | ||
!destinationLZDeployment.sendUln302 || | ||
!destinationLZDeployment.receiveUln302 || | ||
!destinationLZDeployment.executor | ||
) { | ||
throw new Error( | ||
`Can't find sendUln302, receiveUln302 or executor for destination endpoint with eid: "${destinationContract.eid}".` | ||
) | ||
} | ||
|
||
const sourceToDestinationConfig: OmniEdgeHardhat<OAppEdgeConfig> = { | ||
from: sourceContract, | ||
to: destinationContract, | ||
config: { | ||
sendLibrary: sourceLZDeployment.sendUln302.address, | ||
receiveLibraryConfig: { | ||
receiveLibrary: sourceLZDeployment.receiveUln302.address, | ||
gracePeriod: BigInt(0), | ||
}, | ||
sendConfig: { | ||
executorConfig: { | ||
maxMessageSize: 10000, | ||
executor: sourceLZDeployment.executor.address, | ||
}, | ||
ulnConfig: { | ||
confirmations: BigInt(sourceToDestinationConfirmations), | ||
requiredDVNs: sourceRequiredDVNs, | ||
optionalDVNs: sourceOptionalDVNs, | ||
optionalDVNThreshold, | ||
}, | ||
}, | ||
enforcedOptions: enforcedOptionsSrcToDst, | ||
}, | ||
} | ||
|
||
const destinationToSourceConfig: OmniEdgeHardhat<OAppEdgeConfig> = { | ||
from: destinationContract, | ||
to: sourceContract, | ||
config: { | ||
sendLibrary: destinationLZDeployment.sendUln302.address, | ||
receiveLibraryConfig: { | ||
receiveLibrary: destinationLZDeployment.receiveUln302.address, | ||
gracePeriod: BigInt(0), | ||
}, | ||
receiveConfig: { | ||
ulnConfig: { | ||
confirmations: BigInt(sourceToDestinationConfirmations), | ||
requiredDVNs: destinationRequiredDVNs, | ||
optionalDVNs: destinationOptionalDVNs, | ||
optionalDVNThreshold, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
if (destinationToSourceConfirmations) { | ||
sourceToDestinationConfig.config.receiveConfig = { | ||
ulnConfig: { | ||
confirmations: BigInt(destinationToSourceConfirmations), | ||
requiredDVNs: sourceRequiredDVNs, | ||
optionalDVNs: sourceOptionalDVNs, | ||
optionalDVNThreshold, | ||
}, | ||
} | ||
|
||
destinationToSourceConfig.config.enforcedOptions = enforcedOptionsDstToSrc | ||
|
||
destinationToSourceConfig.config.sendConfig = { | ||
executorConfig: { | ||
maxMessageSize: 10000, | ||
executor: destinationLZDeployment.executor.address, | ||
}, | ||
ulnConfig: { | ||
confirmations: BigInt(destinationToSourceConfirmations), | ||
requiredDVNs: destinationRequiredDVNs, | ||
optionalDVNs: destinationOptionalDVNs, | ||
optionalDVNThreshold, | ||
}, | ||
} | ||
} | ||
|
||
configs.push(sourceToDestinationConfig) | ||
configs.push(destinationToSourceConfig) | ||
|
||
return configs | ||
} | ||
|
||
export async function generateConnectionsConfig(pathways: TwoWayConfig[]) { | ||
const metadata = (await fetch(METADATA_URL).then((res) => res.json())) as IMetadata | ||
const connections: OmniEdgeHardhat<OAppEdgeConfig | undefined>[] = [] | ||
|
||
for (const pathway of pathways) { | ||
connections.push(...(await translatePathwayToConfig(pathway, metadata))) | ||
} | ||
|
||
return 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './config-metadata' | ||
export * from './types' |
Oops, something went wrong.